            
/* Single-post 3-col template CSS (api.co.id, item API-038).
   Purpose: layout + styling for the breadcrumb, TOC sidebar, article, and
   banner sidebar grid injected by snippet.php.
   Installed via the wp-add-custom-css plugin (option wpacc_settings,
   head_style output). This file is the SSOT; when it changes, re-apply
   the change to the live wpacc_settings CSS.
   Status: F6 (mobile-only: unified horizontal gutter across every #primary
   section via --apicoid-gutter, and the mobile TOC reworked into a sticky
   top bar with a tap-to-open dropdown, reordered to the top of the mobile
   stack via grid-template-areas; desktop layout unchanged). */

/* API-038 F1: 3-column single-post layout shell (breadcrumb + TOC placeholder + article + banner placeholder) */

/* Brand accent colors, read from the live Astra global color palette
   (astra-settings -> global-color-palette) on 2026-08-04:
   palette[0] #046bd2 = site primary/link accent color (Astra Global Color 1).
   palette[2] #1e293b = site dark/heading color (Astra Global Color 3, slate-navy).
   Used here instead of the generic navy/blue fallback since the real
   brand values were available in the DB. */
:root {
	--apicoid-navy: #1e293b;
	--apicoid-accent: #046bd2;
	/* F6: the single mobile horizontal gutter every #primary section resolves
	   to. Value matches Astra's own .ast-container padding-left/right (20px,
	   unconditional at every viewport width, confirmed in the theme's
	   compiled CSS), which every #primary child already inherits by default.
	   The only outlier was .ast-article-single's own extra inset (Astra's
	   "Separate Container" style), neutralized below inside the 921px mobile
	   media query so article content resolves to this same value instead of
	   stacking an extra padding on top of it. */
	--apicoid-gutter: 20px;
}

/* Astra's narrow-width-container max-width is a hardcoded px value on
   .ast-narrow-container .site-content > .ast-container, not driven by the
   --ast-narrow-container-width CSS var for the classic single template.
   Override it directly, scoped to single-post only. */
body.single-post.ast-narrow-container .site-content > .ast-container {
	max-width: 1240px !important;
}

.single-post #primary {
	display: grid;
	grid-template-columns: 240px minmax(0, 1fr) 300px;
	grid-template-areas:
		"bc bc bc"
		"toc main banner";
	column-gap: 32px;
	row-gap: 16px;
	/* align-items: stretch (the default) is required here, not "start": the
	   toc/banner grid items must stretch to the full row height (matching the
	   tall article column) so their sticky inner child has room to travel and
	   actually stick while scrolling. With "start" the item box shrinks to its
	   own short content and position:sticky has nowhere to stick. */
	align-items: stretch;
}

.single-post #primary > .apicoid-breadcrumb {
	grid-area: bc;
}

.single-post #primary > .apicoid-toc-col {
	grid-area: toc;
}

/* API-042: direct child #primary yang sebenarnya adalah 
   (Astra membungkus  satu level lebih dalam, lihat snippet.php),
   jadi intent min-width:0 pada grid item harus menyasar > main, bukan
   > article (selector lama tidak pernah match grid-item asli sehingga ia
   tetap min-width:auto — inilah yang membuat / lebar menarik
   track mobile tunggal melebar). */
.single-post #primary > main {
	grid-area: main;
	min-width: 0;
}

.single-post #primary > .apicoid-banner-col {
	grid-area: banner;
}

/* API-042: guard overflow untuk konten body yang lebar. Akar masalah
   mobile adalah track grid tunggal yang ditarik melebar oleh /
   lebar (diperbaiki via minmax(0,1fr) pada track mobile + min-width:0 pada
   grid item asli di atas); rule-rule ini defense-in-depth agar SETIAP
   elemen konten lebar (tabel, code block, media, string panjang tanpa
   spasi) tetap di dalam kolom artikel, bukan melebarkan halaman, di semua
   viewport. Guard hanya menyasar elemen pelaku DI DALAM .entry-content,
   tidak pernah ancestor kolom sticky TOC/banner (overflow pada ancestor
   sticky mematikan position:sticky, pelajaran build-log). */
.single-post .entry-content {
	overflow-wrap: break-word;
	word-wrap: break-word;
}

.single-post .entry-content img,
.single-post .entry-content video {
	max-width: 100%;
	height: auto;
}

.single-post .entry-content figure,
.single-post .entry-content iframe,
.single-post .entry-content embed,
.single-post .entry-content object {
	max-width: 100%;
}

.single-post .entry-content pre {
	max-width: 100%;
	overflow-x: auto;
}

.single-post .entry-content table {
	display: block;
	width: 100%;
	max-width: 100%;
	overflow-x: auto;
}

/* F5: the banner column is now only rendered by PHP when the sidebar_banner
   module is enabled + fully configured (see snippet.php); when it is
   disabled/unconfigured, .apicoid-banner-col is simply absent from the DOM.
   Without this rule the "banner" grid-template-areas slot would sit empty
   (still reserving its 300px column), so collapse the layout to 2 columns
   whenever that aside is missing, keeping the grid genuinely valid (no
   empty gap) in both the banner-ON and banner-OFF states.
   Bugfix (2026-08-05): this is a DESKTOP-only concern (closing the empty
   300px banner column in the multi-column layout); on mobile the layout is
   already single-column. Gated to min-width:922px (the desktop side of the
   921px mobile breakpoint) so its higher selector specificity (:has()) can
   no longer override the max-width:921px single-column rule below when the
   banner is absent, which is what broke prod (launched banner-OFF, a state
   staging never exercised since staging kept the banner ON). */
@media (min-width: 922px) {
	.single-post #primary:not(:has(> .apicoid-banner-col)) {
		grid-template-columns: 240px minmax(0, 1fr);
		grid-template-areas:
			"bc bc"
			"toc main";
	}
}

/* Smooth-scroll for TOC anchor jumps, plus enough top offset so headings
   don't land underneath the sticky header. */
html {
	scroll-behavior: smooth;
}

.single-post .entry-content h2,
.single-post .entry-content h3 {
	scroll-margin-top: 110px;
}

/* Sticky styling lives on the INNER child, not the outer grid-item column:
   the outer .apicoid-toc-col/.apicoid-banner-col now stretch to the full row
   height (see align-items above), so the visible bordered box must be the
   inner element that sizes to its own content and sticks within that tall
   parent while scrolling. */
.apicoid-toc-sticky,
.apicoid-banner-sticky {
	position: sticky;
	top: 100px;
	padding: 16px;
}

.apicoid-banner-sticky {
	border: 1px solid #e0e0e0;
}

/* TOC card: white card, soft border + shadow, not a plain box. */
.apicoid-toc-sticky {
	background: #f8fafc;
	border: 1px solid #e2e8f0;
	border-radius: 10px;
	box-shadow: 0 1px 3px rgba(15, 23, 42, 0.06), 0 1px 2px rgba(15, 23, 42, 0.04);
}

.apicoid-toc-title {
	margin: 0 0 12px;
	padding-left: 10px;
	border-left: 3px solid var(--apicoid-accent);
	font-size: 0.8rem;
	font-weight: 700;
	letter-spacing: 0.06em;
	text-transform: uppercase;
	color: var(--apicoid-navy);
}

/* F6: caret icon is part of the mobile sticky-bar toggle affordance only;
   hidden here (desktop / default) so the desktop TOC title is visually
   identical to before. Shown + wired to rotate inside the 921px mobile
   media query below. */
.apicoid-toc-caret {
	display: none;
}

.apicoid-toc-list {
	list-style: none;
	margin: 0;
	padding: 0;
	display: flex;
	flex-direction: column;
	gap: 4px;
}

.apicoid-toc-item a {
	display: block;
	padding: 6px 10px;
	border-left: 3px solid transparent;
	border-radius: 4px;
	color: #334155;
	font-size: 0.9rem;
	line-height: 1.4;
	text-decoration: none;
	transition: color 0.15s ease, background-color 0.15s ease, padding-left 0.15s ease;
}

.apicoid-toc-item a:hover {
	color: var(--apicoid-accent);
	background: rgba(4, 107, 210, 0.06);
	padding-left: 14px;
}

.apicoid-toc-item.level-h3 a {
	padding-left: 22px;
	font-size: 0.85rem;
	color: #64748b;
}

.apicoid-toc-item.level-h3 a:hover {
	padding-left: 26px;
}

.apicoid-toc-item a.is-active {
	color: var(--apicoid-accent);
	font-weight: 600;
	background: rgba(4, 107, 210, 0.08);
	border-left-color: var(--apicoid-accent);
}

/* Dev fallback only: not emitted in production output as of F5 (the banner
   callback now returns early instead of printing a placeholder when
   unconfigured), kept here in case a manual placeholder is ever wanted for
   local testing. */
.apicoid-banner-placeholder {
	background: #e5e5e5;
	min-height: 600px;
	width: 300px;
	display: flex;
	align-items: center;
	justify-content: center;
	text-align: center;
	color: #666;
}

/* F5: dynamic banner image/link, rendered from the apicoid_site_config
   option. Rounded corners + subtle border to match the card language used
   elsewhere (TOC card, related cards); hover lift for affordance since the
   whole banner is a single clickable link. */
.apicoid-banner-link {
	display: block;
	overflow: hidden;
	border-radius: 10px;
	transition: transform 0.15s ease, box-shadow 0.15s ease;
}

.apicoid-banner-link:hover {
	transform: translateY(-2px);
	box-shadow: 0 8px 20px rgba(15, 23, 42, 0.1);
}

.apicoid-banner-img {
	display: block;
	width: 100%;
	height: auto;
}

/* Breadcrumb: small muted trail with a navy current item, chevron
   separators between the plain-text " > " tokens already output by PHP. */
.apicoid-breadcrumb {
	background: #f8fafc;
	border: 1px solid #e2e8f0;
	border-radius: 8px;
	padding: 8px 14px;
	font-size: 0.85em;
	color: #64748b;
}

.apicoid-breadcrumb a {
	color: #64748b;
	text-decoration: none;
}

.apicoid-breadcrumb a:hover {
	color: var(--apicoid-accent);
	text-decoration: underline;
}

.apicoid-breadcrumb span {
	color: var(--apicoid-navy);
	font-weight: 600;
}

/* API-038 F3: featured image + meta line prepended into .entry-content, and
   a previous/next post nav appended after .entry-content. */

/* Astra's own single-post entry-meta (author/date, shown under the title in
   .entry-header) is hidden here instead of via a DB setting change: we
   render our own meta line (.apicoid-meta, below) inside .entry-content
   instead, so the DB-level Astra structure option is left untouched. */
.single-post .entry-header .entry-meta {
	display: none;
}

.apicoid-featured {
	margin: 0 0 20px;
}

.apicoid-featured img {
	display: block;
	width: 100%;
	height: auto;
	border-radius: 12px;
}

.apicoid-meta {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 6px;
	margin: 0 0 16px;
	font-size: 0.9rem;
	color: #64748b;
}

.apicoid-meta-author span {
	color: var(--apicoid-navy);
	font-weight: 600;
}

.apicoid-meta a {
	color: var(--apicoid-accent);
	text-decoration: none;
}

.apicoid-meta a:hover {
	text-decoration: underline;
}

.apicoid-meta .sep {
	color: #cbd5e1;
}

.apicoid-adjacent {
	display: grid;
	grid-template-columns: 1fr 1fr;
	gap: 16px;
	margin: 40px 0 8px;
}

/* Whichever side (prev/next) has no adjacent post is left empty by PHP
   (no dead link); collapse that empty grid cell instead of showing a
   blank card. */
.apicoid-adjacent-side:empty {
	display: none;
}

.apicoid-adjacent-side a {
	display: block;
	height: 100%;
	padding: 16px 18px;
	border: 1px solid #e2e8f0;
	border-radius: 10px;
	text-decoration: none;
	transition: border-color 0.15s ease, transform 0.15s ease, box-shadow 0.15s ease;
}

.apicoid-adjacent-side a:hover {
	border-color: var(--apicoid-accent);
	transform: translateY(-2px);
	box-shadow: 0 4px 10px rgba(15, 23, 42, 0.08);
}

.apicoid-adjacent-label {
	display: block;
	margin-bottom: 6px;
	font-size: 0.75rem;
	font-weight: 700;
	letter-spacing: 0.04em;
	text-transform: uppercase;
	color: #94a3b8;
}

.apicoid-adjacent-title {
	display: -webkit-box;
	-webkit-line-clamp: 2;
	-webkit-box-orient: vertical;
	overflow: hidden;
	font-size: 1rem;
	font-weight: 600;
	line-height: 1.4;
	color: var(--apicoid-navy);
}

.apicoid-adjacent-side a:hover .apicoid-adjacent-title {
	color: var(--apicoid-accent);
}

/* Mirror the next-post card so its text aligns toward the outer edge,
   matching the visual "forward" direction; reset to left on mobile stack. */
.apicoid-adjacent-next {
	text-align: right;
}

/* API-038 F4: share bar, in-body "Baca juga" callout, author box, and a
   full-width related-posts grid. */

/* Share-to-social bar: round icon buttons, accent fill on hover/copied. */
.apicoid-share {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 10px;
	margin: 0 0 28px;
}

.apicoid-share-label {
	font-size: 0.78rem;
	font-weight: 700;
	letter-spacing: 0.04em;
	text-transform: uppercase;
	color: #94a3b8;
}

.apicoid-share-links {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 8px;
}

.apicoid-share-btn {
	position: relative;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	box-sizing: border-box;
	width: 36px;
	height: 36px;
	aspect-ratio: 1;
	flex-shrink: 0;
	margin: 0;
	padding: 0;
	border: 1px solid #e2e8f0;
	border-radius: 50%;
	background: #f8fafc;
	color: #64748b;
	font: inherit;
	line-height: 1;
	text-decoration: none;
	appearance: none;
	-webkit-appearance: none;
	overflow: hidden;
	cursor: pointer;
	transition: background-color 0.15s ease, border-color 0.15s ease, color 0.15s ease, transform 0.15s ease;
}

.apicoid-share-btn:hover,
.apicoid-share-btn:focus-visible {
	background: var(--apicoid-accent);
	border-color: var(--apicoid-accent);
	color: #fff;
	transform: translateY(-2px);
}

.apicoid-share-btn.is-copied {
	background: var(--apicoid-accent);
	border-color: var(--apicoid-accent);
	color: #fff;
}

.apicoid-share-copy-feedback {
	position: absolute;
	bottom: calc(100% + 8px);
	left: 50%;
	transform: translateX(-50%) translateY(4px);
	padding: 3px 8px;
	border-radius: 6px;
	background: var(--apicoid-navy);
	color: #fff;
	font-size: 0.7rem;
	font-weight: 600;
	white-space: nowrap;
	opacity: 0;
	pointer-events: none;
	transition: opacity 0.15s ease, transform 0.15s ease;
}

.apicoid-share-copy.is-copied .apicoid-share-copy-feedback {
	opacity: 1;
	transform: translateX(-50%) translateY(0);
}

/* In-body "Baca juga" callout: distinct from the article body, accent
   left border + tinted background so it reads as an interruption, not
   more body copy. */
.apicoid-inline-related {
	margin: 28px 0;
	padding: 16px 20px;
	border-left: 4px solid var(--apicoid-accent);
	border-radius: 8px;
	background: rgba(4, 107, 210, 0.05);
}

.apicoid-inline-related-label {
	display: block;
	margin-bottom: 8px;
	font-size: 0.75rem;
	font-weight: 700;
	letter-spacing: 0.05em;
	text-transform: uppercase;
	color: var(--apicoid-accent);
}

.apicoid-inline-related-list {
	display: flex;
	flex-direction: column;
	gap: 6px;
	margin: 0;
	padding: 0;
	list-style: none;
}

.apicoid-inline-related-list a {
	color: var(--apicoid-navy);
	font-weight: 600;
	text-decoration: none;
}

.apicoid-inline-related-list a:hover {
	color: var(--apicoid-accent);
	text-decoration: underline;
}

/* Author box: horizontal card, round avatar left, name/bio/link right. */
.apicoid-author {
	display: flex;
	gap: 18px;
	align-items: flex-start;
	margin: 40px 0 8px;
	padding: 20px;
	border: 1px solid #e2e8f0;
	border-radius: 12px;
	background: #f8fafc;
}

.apicoid-author-avatar img {
	display: block;
	width: 72px;
	height: 72px;
	border-radius: 50%;
}

.apicoid-author-role {
	display: block;
	margin-bottom: 2px;
	font-size: 0.72rem;
	font-weight: 700;
	letter-spacing: 0.05em;
	text-transform: uppercase;
	color: var(--apicoid-accent);
}

.apicoid-author-name {
	margin: 0 0 6px;
	font-size: 1.05rem;
	font-weight: 700;
	color: var(--apicoid-navy);
}

.apicoid-author-bio {
	margin: 0 0 10px;
	font-size: 0.9rem;
	line-height: 1.5;
	color: #64748b;
}

.apicoid-author-link {
	font-size: 0.85rem;
	font-weight: 600;
	color: var(--apicoid-accent);
	text-decoration: none;
}

.apicoid-author-link:hover {
	text-decoration: underline;
}

/* Full-width related-posts grid. .apicoid-related is a direct #primary
   child (see snippet.php astra_primary_content_bottom comment), so
   grid-column: 1 / -1 actually has a full-width row to expand into,
   spanning below the "toc main banner" row instead of being confined to
   the center column. */
.single-post #primary > .apicoid-related {
	grid-column: 1 / -1;
	margin: 12px 0 0;
}

.apicoid-related-title {
	margin: 0 0 20px;
	padding-left: 12px;
	border-left: 4px solid var(--apicoid-accent);
	font-size: 1.3rem;
	font-weight: 700;
	color: var(--apicoid-navy);
}

.apicoid-related-grid {
	display: grid;
	grid-template-columns: repeat(3, minmax(0, 1fr));
	gap: 24px;
}

.apicoid-related-card {
	display: flex;
	flex-direction: column;
	overflow: hidden;
	border: 1px solid #e2e8f0;
	border-radius: 12px;
	background: #fff;
	transition: transform 0.15s ease, box-shadow 0.15s ease, border-color 0.15s ease;
}

.apicoid-related-card:hover {
	border-color: var(--apicoid-accent);
	box-shadow: 0 8px 20px rgba(15, 23, 42, 0.08);
	transform: translateY(-3px);
}

.apicoid-related-thumb {
	display: block;
	aspect-ratio: 16 / 10;
	background: #e2e8f0;
}

.apicoid-related-thumb img {
	display: block;
	width: 100%;
	height: 100%;
	object-fit: cover;
}

.apicoid-related-thumb-placeholder {
	display: block;
	width: 100%;
	height: 100%;
	background: linear-gradient(135deg, #e2e8f0, #f1f5f9);
}

.apicoid-related-body {
	display: flex;
	flex-direction: column;
	gap: 6px;
	padding: 16px 18px 18px;
}

.apicoid-related-cat {
	font-size: 0.72rem;
	font-weight: 700;
	letter-spacing: 0.04em;
	text-transform: uppercase;
	color: var(--apicoid-accent);
}

.apicoid-related-card-title {
	margin: 0;
	font-size: 1rem;
	font-weight: 600;
	line-height: 1.4;
}

.apicoid-related-card-title a {
	display: -webkit-box;
	-webkit-line-clamp: 2;
	-webkit-box-orient: vertical;
	overflow: hidden;
	color: var(--apicoid-navy);
	text-decoration: none;
}

.apicoid-related-card:hover .apicoid-related-card-title a {
	color: var(--apicoid-accent);
}

.apicoid-related-date {
	font-size: 0.78rem;
	color: #94a3b8;
}

@media (max-width: 900px) {
	.apicoid-related-grid {
		grid-template-columns: repeat(2, minmax(0, 1fr));
	}
}

@media (max-width: 560px) {
	.apicoid-related-grid {
		grid-template-columns: 1fr;
	}

	.apicoid-author {
		flex-direction: column;
		align-items: flex-start;
	}
}

@media (max-width: 921px) {
	/* F6: TOC now sits right after the breadcrumb (a sticky top bar), ahead
	   of the article, instead of dropping to the very bottom of the stack
	   below the author box / prev-next nav. Pure grid-template-areas
	   reorder, no DOM change and no JS "order" hack needed. */
	.single-post #primary {
		/* API-042: minmax(0,1fr), bukan 1fr polos: track 1fr punya automatic
		   minimum "auto" (min-content isi) sehingga / lebar bisa
		   menariknya melebihi lebar container (grid blowout). minmax(0,...)
		   mengunci floor track ke 0 seperti versi desktop. */
		grid-template-columns: minmax(0, 1fr);
		grid-template-areas:
			"bc"
			"toc"
			"main"
			"banner";
	}

	.apicoid-banner-sticky {
		position: static;
	}

	.apicoid-banner-col {
		display: flex;
		justify-content: center;
	}

	/* Force the breadcrumb to a single line on mobile: no wrap, overflow
	   truncated with an ellipsis instead of wrapping to a second line. */
	.apicoid-breadcrumb {
		display: block;
		white-space: nowrap;
		overflow: hidden;
		text-overflow: ellipsis;
	}

	.apicoid-breadcrumb a,
	.apicoid-breadcrumb span {
		white-space: nowrap;
	}

	/* Prev/next nav stacks to 1 column on mobile; reset the next-card's
	   right-alignment back to left so it reads naturally when stacked. */
	.apicoid-adjacent {
		grid-template-columns: 1fr;
	}

	.apicoid-adjacent-next {
		text-align: left;
	}

	/* F6 PROBLEM 1: unify the mobile horizontal gutter. Root cause was
	   Astra's "Separate Container" style (.ast-article-single, active
	   whenever the viewport is &lt;=1200px, so still active at this 921px
	   breakpoint) giving the article its own extra 2.4em left/right padding
	   on top of the ambient --apicoid-gutter every #primary child already
	   gets from Astra&#039;s .ast-container (20px, unconditional). Every
	   full-width #primary child (breadcrumb, this TOC bar, banner column,
	   related grid) has no such extra padding, so they sat --apicoid-gutter
	   from the edge while the article sat --apicoid-gutter + 2.4em in,
	   producing the ragged margin Rendy flagged. Zeroing just the article&#039;s
	   own side padding here (top/bottom padding, the vertical rhythm, is
	   untouched) makes it resolve to the exact same --apicoid-gutter as
	   everything else, with nothing else needing to move. Desktop is
	   untouched (this rule lives inside the mobile media query only). */
	.single-post #primary .ast-article-single {
		padding-left: 0;
		padding-right: 0;
	}

	/* F6 PROBLEM 2: mobile TOC becomes a sticky top bar with a tap-to-open
	   dropdown. position:sticky is already set at the base (desktop) rule
	   above; here it just re-points to the viewport top (instead of the
	   100px offset used for the desktop side column) and the card gets the
	   collapsed/expanded treatment. The site header is position:relative
	   (not fixed/sticky, confirmed F1), so top:0 sticks cleanly with nothing
	   to clash with. */
	.apicoid-toc-sticky {
		top: 14px;
		z-index: 40;
		padding: 0;
		overflow: hidden;
	}

	.apicoid-toc-title {
		display: flex;
		align-items: center;
		justify-content: space-between;
		gap: 10px;
		margin: 0;
		padding: 14px var(--apicoid-gutter);
		cursor: pointer;
		user-select: none;
	}

	.apicoid-toc-caret {
		display: block;
		flex-shrink: 0;
		transition: transform 0.2s ease;
	}

	.apicoid-toc.is-open .apicoid-toc-caret {
		transform: rotate(180deg);
	}

	/* Collapsed by default: max-height/opacity transition (not display:none)
	   so the open/close is a smooth animation, not an instant snap. */
	.apicoid-toc-list {
		max-height: 0;
		opacity: 0;
		gap: 2px;
		overflow: hidden;
		margin: 0;
		padding: 0 var(--apicoid-gutter);
		transition: max-height 0.25s ease, opacity 0.2s ease, padding 0.25s ease;
	}

	.apicoid-toc.is-open .apicoid-toc-list {
		max-height: 60vh;
		opacity: 1;
		overflow-y: auto;
		padding: 4px var(--apicoid-gutter) 14px;
	}
}

        