/* ===========================================================================
   Portfolio template
   styles.css  —  shared stylesheet for the PHP site (Classic look)
   ---------------------------------------------------------------------------
   Re-skin the whole site from one place: edit the CSS variables in :root
   (light theme) and html[data-theme="dark"] (dark theme) below.
   The Settings panel (owner-only) writes overrides into these same variables.
   =========================================================================== */

:root {
  /* ---- Palette (light) ---- */
  --bg:#FAFAFC; --surface:#FFFFFF; --ink:#16161F; --ink-2:#363744; --soft:#62636F; --faint:#70717F;
  --line:#E7E7EC;
  /* The bracket connectors in Visual style. --line is tuned for box borders
     and is too faint for a 1px rule floating in whitespace. Mixed TOWARD
     --faint rather than hard-coded, so it gains contrast in the dark skins
     too — there --line is dark and --faint is light, and the mix still
     moves away from the background either way. */
  --conn-line:color-mix(in srgb, var(--line) 45%, var(--faint)); --hair:#F0F0F4;
  --accent:#4039D9; --accent-2:#332DBA; --accent-soft:#ECEBFB; --accent-ink:#211C7A;
  /* Text sitting ON the --accent FILL (the A/D/D/I/E chips, the active
     category tab). This was hardcoded #fff in 20 rules, which works on a
     light theme's deep accent and fails on every dark theme's light one —
     white on Night Class's gold measured 2.10. Each theme names its own. */
  --on-accent:#FFFFFF;   /* 7.49:1 */
  /* --accent used AS TEXT. Split from --accent because that token is also a
     BACKGROUND in 25 rules, and the two pull in opposite directions: darkening
     it to make link text readable on a light page simultaneously darkens the
     fill under Bold's near-black label text. Defaults to --accent, so a skin
     only declares this when its accent fails as text. */
  --accent-text:var(--accent);
  --ok:#1F8A5B; --warn:#C2541F;

  --maxw:1180px;
  --radius:16px; --radius-sm:10px;
  /* Standard image aspect ratios — referenced everywhere images render, so the
     whole site stays on a small, consistent set instead of ad-hoc values. */
  --ar-square:1/1; --ar-video:16/9;
  --f-display:"Space Grotesk", system-ui, sans-serif;
  --f-sans:"Hanken Grotesk", system-ui, sans-serif;
  --f-mono:ui-monospace, "SF Mono", Menlo, monospace;

  /* CTA (Contact button) defaults to the accent; the Visual Style editor can
     give it its own color. Typography knobs scale the whole type system. */
  /* --cta-ink follows --on-accent because --cta IS --accent by default: the ink
     that reads on the accent fill is the ink that reads on the button. It was a
     hardcoded #fff, which meant classic's dark theme put white on its
     deliberately-light dark-mode accent — 3.71, and the buttons are 14-15px at
     weight 600, so no large-text exemption applies. A skin that points --cta
     somewhere other than --accent (Syllabus does) still names its own. */
  --cta:var(--accent); --cta-2:var(--accent-2); --cta-ink:var(--on-accent);
  --f-scale:1; --f-head-weight:600; --f-head-tracking:-0.02em;

  /* Ink for the uppercase micro-labels on a resource detail page — "SKILLS"
     (.ds-label), "TRAINING TIME" (.spec-label), "FOR THE FACILITATOR"
     (.frp-group). They share one token on purpose: they are the same 10.56px
     /600 treatment stacked down the same column, so a value that moves one
     has to move all three or the parts list stops matching the Skills label
     directly above it.

     Why not --faint, which they used to take: at 10.56px/600 WCAG counts these
     as NORMAL text (large-text 3:1 needs 24px, or 18.66px at weight 700), so
     they owe 4.5:1 — and --faint measured 2.65:1 on classic, 2.18:1 on warm,
     3.22:1 on syllabus. --soft clears 4.5:1 on every skin and both themes; the
     only places it doesn't are saturated section bands, which the two band
     skins override for themselves (see skin-bold.css / skin-warm.css).

     Derived from --soft rather than a fixed hex so it inherits per-skin and
     per-theme, and so it rides the owner's "Muted text" role in the Visual
     Style editor — --faint is wired to no control at all, so a label that
     failed there could not be corrected by the owner. */
  --label-ink:var(--soft);

  /* Sticky-stack offsets. Three layers pin on top of each other on a resource
     page — .top (top:0), .addie-nav, then .detail-section .section-head — and
     each one's offset is just the measured height of everything above it. That
     arithmetic was inlined at three call sites, so a skin that made the top bar
     taller broke it silently: filmstrip's 10px sprocket strip plus its 3px rule
     put the bar at 83px while the ADDIE nav went on pinning at 70px, sliding
     13px of the nav under an opaque bar — it looked squashed as you scrolled.
     A skin that changes the height of either bar overrides these three and
     nothing else. --stick-nav is the top bar's height minus its bottom border,
     so the nav tucks under the rule instead of doubling it. */
  --stick-nav:70px;      /* .addie-nav pin: .top is 71px incl. a 1px border */
  --stick-head:126px;    /* .section-head pin: 71 + 45px nav + 10px breathing */
  --stick-anchor:132px;  /* jump targets: the same stack + 16px */
}
html[data-theme="dark"] {
  --bg:#121218; --surface:#1A1A22; --ink:#ECECF2; --ink-2:#C9C9D3; --soft:#AEAFBE; --faint:#888997;
  --line:#2A2A33; --hair:#1F1F27;
  --accent:#7C75F0; --accent-2:#9C96F7; --accent-soft:#22203A; --accent-ink:#D6D2FB;
  /* Text sitting ON the --accent FILL (the A/D/D/I/E chips, the active
     category tab). This was hardcoded #fff in 20 rules, which works on a
     light theme's deep accent and fails on every dark theme's light one —
     white on Night Class's gold measured 2.10. Each theme names its own. */
  --on-accent:#14110D;   /* 5.07:1 */
  --ok:#57D89B; --warn:#F2A877;
}

* { box-sizing:border-box; }
html { scroll-behavior:smooth; font-size:calc(100% * var(--f-scale, 1)); }
body {
  margin:0; background:var(--bg); color:var(--ink);
  font-family:var(--f-sans); font-size:calc(17px * var(--f-scale, 1)); line-height:1.6;
  -webkit-font-smoothing:antialiased;
  transition:background-color .3s ease, color .3s ease;
}
.wrap { width:100%; max-width:var(--maxw); margin-inline:auto; padding-inline:32px; }
a { color:inherit; text-decoration:none; }
h1,h2,h3,h4 { margin:0; line-height:1.08; letter-spacing:var(--f-head-tracking, -0.02em); font-family:var(--f-display); font-weight:var(--f-head-weight, 600); }
.eyebrow { font-size:0.72rem; font-weight:600; letter-spacing:0.16em; text-transform:uppercase; color:var(--accent-text); }
.ph-label { font-family:var(--f-mono); font-size:0.72rem; letter-spacing:0.16em; text-transform:uppercase; color:var(--faint); }

/* ---------------------------------------------------------------------------
   Top bar
   --------------------------------------------------------------------------- */
.top { position:sticky; top:0; z-index:50; background:color-mix(in srgb, var(--surface) 86%, transparent); backdrop-filter:blur(12px); border-bottom:1px solid var(--line); }
.top .wrap { display:flex; align-items:center; gap:14px; height:70px; position:relative; }
.brand { display:flex; align-items:center; gap:12px; white-space:nowrap; }
.brand-mark { height:30px; width:auto; color:var(--accent-text); flex:none; }
.brand .name { font-family:var(--f-display); font-weight:700; font-size:1.1rem; letter-spacing:-0.02em; }
.brand .role { font-size:0.88rem; color:var(--soft); padding-inline-start:12px; border-inline-start:1px solid var(--line); }
.top .spacer { flex:1; }
.topbar-tools { display:flex; align-items:center; gap:18px; }
.topbar-toggles { display:flex; align-items:center; gap:10px; }
.nav-link { font-family:var(--f-sans); font-weight:600; font-size:0.92rem; color:var(--ink); padding:6px 4px; border-radius:8px; }
.nav-link:hover, .nav-link.is-current { color:var(--accent-text); }

/* Hamburger: hidden on desktop, revealed when the top bar collapses.
   Scoped to .top so it beats .iconbtn's display:grid regardless of source order. */
.top .hamburger { display:none; flex:none; }
.hamburger .i-close { display:none; }
.hamburger[aria-expanded="true"] .i-bars { display:none; }
.hamburger[aria-expanded="true"] .i-close { display:block; }

.seg { display:inline-flex; background:var(--bg); border:1px solid var(--line); border-radius:10px; padding:3px; }
.seg a, .seg button { appearance:none; border:0; cursor:pointer; font-family:var(--f-sans); font-size:0.8rem; font-weight:600; color:var(--soft); background:transparent; padding:6px 13px; border-radius:7px; transition:color .15s; }
.seg a[aria-current="true"], .seg button[aria-pressed="true"] { background-color:var(--accent); color:#fff; }

.iconbtn { appearance:none; cursor:pointer; width:38px; height:38px; border-radius:10px; border:1px solid var(--line); background:var(--surface); color:var(--soft); display:grid; place-items:center; transition:background .2s, color .2s, border-color .2s; }
.iconbtn:hover { color:var(--accent-text); border-color:var(--accent); }
.iconbtn svg { width:18px; height:18px; }
.i-sun { display:none; }
.i-moon { display:block; }
html[data-theme="dark"] .i-sun { display:block; }
html[data-theme="dark"] .i-moon { display:none; }

.cta, .btn { font-family:var(--f-sans); font-weight:600; font-size:0.92rem; cursor:pointer; border-radius:10px; padding:11px 22px; border:1.5px solid transparent; display:inline-flex; align-items:center; gap:9px; white-space:nowrap; transition:background .2s, color .2s, transform .15s, border-color .2s; }
.cta, .btn-primary { background:var(--cta); color:var(--cta-ink, #fff); }
.cta:hover, .btn-primary:hover { background:var(--cta-2); color:var(--cta-ink, #fff); transform:translateY(-1px); }
.btn-ghost { border-color:var(--line); color:var(--ink); background:var(--surface); }
.btn-ghost:hover { border-color:var(--accent); color:var(--accent-text); }
.btn-block { width:100%; justify-content:center; padding:14px; font-size:1rem; }

/* ---------------------------------------------------------------------------
   Hero
   --------------------------------------------------------------------------- */
.hero { padding:76px 0 34px; }
.hero .wrap { display:grid; grid-template-columns:1fr 270px; gap:56px; align-items:center; }
.hero .eyebrow { margin-bottom:20px; }
.hero h1 { font-size:clamp(2.6rem,5.4vw,4.2rem); font-weight:600; letter-spacing:-0.03em; line-height:1.0; }
.hero h1 .accent-text { color:var(--accent-text); }
.hero .lede { margin:26px 0 0; font-size:1.12rem; color:var(--ink-2); max-width:50ch; }
.hero-actions { display:flex; gap:12px; margin-top:30px; flex-wrap:wrap; }
.caps { margin-top:34px; padding-top:20px; border-top:1px solid var(--line); }
.caps .caps-label { font-size:0.68rem; font-weight:600; letter-spacing:0.14em; text-transform:uppercase; color:var(--soft); margin-bottom:8px; }
.caps .list { color:var(--ink-2); font-size:0.98rem; }
.caps .list .dot { color:var(--accent-text); margin:0 9px; }
.headshot { aspect-ratio:var(--ar-square); border-radius:18px; background:repeating-linear-gradient(135deg, var(--hair) 0 14px, var(--bg) 14px 15px); border:1px solid var(--line); display:grid; place-items:center; overflow:hidden; }
.headshot img { width:100%; height:100%; object-fit:cover; }

/* ---- About page ---- */
.about-hero { padding-bottom:20px; }
.about-body { max-width:62ch; margin-top:8px; }
.about-body p { margin:0 0 1.1em; font-size:1.12rem; line-height:1.7; color:var(--ink-2); }
.about-body p:last-child { margin-bottom:0; }
/* Rich-text prose fields (the intro ledes + About body) now hold real block
   markup — reset the spacing of the paragraphs/lists/quotes they contain so a
   single-line intro still looks like one, and lists/indents render tidily. */
.about-body blockquote, .lede blockquote { margin-block:0 1.1em; margin-inline-start:1.4em; margin-inline-end:0; }
.lede p { margin:0 0 .7em; }
.lede p:last-child { margin-bottom:0; }
.lede ul, .lede ol { margin:.5em 0 .7em; padding-inline-start:1.4em; }
.lede li { margin-bottom:.25em; }

/* ---------------------------------------------------------------------------
   Selected work — category tabs + project rows
   --------------------------------------------------------------------------- */
.work { padding:48px 0 40px; }
.work-head { margin-bottom:22px; }
.work-head h2 { font-size:clamp(1.9rem,3.8vw,2.7rem); font-weight:600; margin-bottom:18px; }
.tabs { display:flex; gap:8px; flex-wrap:wrap; }
.tabs .tab { font-family:var(--f-sans); font-size:0.88rem; font-weight:600; color:var(--soft); background:var(--surface); border:1px solid var(--line); padding:9px 17px; border-radius:999px; cursor:pointer; transition:all .18s; }
.tabs .tab:hover { border-color:var(--accent); color:var(--accent-text); }
.tabs .tab.active { background:var(--accent); border-color:var(--accent); color:var(--on-accent); }
.tabs .tab .n { opacity:.6; margin-inline-start:6px; font-variant-numeric:tabular-nums; }

.catgroup { padding-top:34px; }
.catgroup .cat-label { display:flex; align-items:center; gap:14px; margin-bottom:20px; }
.catgroup .cat-label h3 { font-size:1.3rem; font-weight:600; }
.catgroup .cat-label .rule { flex:1; height:1px; background:var(--line); }
.catgroup .cat-label .count { font-size:0.78rem; color:var(--soft); font-weight:600; }

.proj-list { display:flex; flex-direction:column; gap:16px; }
.proj-row { display:flex; flex-direction:row; align-items:stretch; text-decoration:none; color:inherit; background:var(--surface); border:1px solid var(--line); border-radius:16px; overflow:hidden; box-shadow:0 1px 3px rgba(22,22,31,0.05),0 2px 6px rgba(22,22,31,0.03); transition:transform .18s ease, box-shadow .22s ease, border-color .2s; position:relative; }
.proj-row:not(.placeholder):hover { transform:translateY(-4px); box-shadow:0 18px 36px -18px color-mix(in srgb,var(--accent) 60%,transparent); border-color:color-mix(in srgb,var(--accent) 45%,var(--line)); }
.proj-row:not(.placeholder):active { transform:translateY(-1px); box-shadow:0 1px 3px rgba(22,22,31,0.05); transition-duration:.06s; }
.proj-row:not(.placeholder):hover .proj-arrow { color:var(--accent-text); }
.proj-row:not(.placeholder):hover .proj-arrow .ar { transform:translateX(6px); }
.proj-thumb { flex:none; width:38%; max-width:340px; aspect-ratio:var(--ar-video); background:var(--accent-soft); background-image:repeating-linear-gradient(135deg, transparent 0 15px, color-mix(in srgb,var(--accent) 6%,transparent) 15px 16px); display:grid; place-items:center; border-inline-end:1px solid var(--line); position:relative; }
.proj-thumb .ph { font-size:0.68rem; letter-spacing:0.16em; text-transform:uppercase; color:color-mix(in srgb,var(--accent) 50%,var(--faint)); font-family:var(--f-mono); }
.proj-thumb img { position:absolute; inset:0; width:100%; height:100%; object-fit:cover; }
.tag-soon { position:absolute; top:13px; inset-inline-start:13px; display:inline-block; font-size:0.64rem; font-weight:700; letter-spacing:0.08em; text-transform:uppercase; background:var(--surface); color:var(--soft); border:1px solid var(--line); padding:5px 10px; border-radius:7px; white-space:nowrap; }
.proj-body { display:flex; flex-direction:column; gap:7px; padding:24px 28px; justify-content:center; flex:1; }
.proj-body .resource { font-size:0.7rem; font-weight:700; letter-spacing:0.1em; text-transform:uppercase; color:var(--accent-text); }
.proj-body h4 { font-size:1.3rem; font-weight:600; line-height:1.2; }
.proj-body .blurb { font-size:0.94rem; color:var(--soft); margin:0; line-height:1.55; }
.proj-footer { display:flex; align-items:center; gap:14px; margin-top:6px; }
.proj-arrow { font-size:0.86rem; font-weight:600; color:var(--ink); display:inline-flex; align-items:center; gap:7px; transition:color .2s; }
.proj-arrow .ar { color:var(--accent-text); display:inline-block; transition:transform .2s; }
.proj-row.placeholder .proj-thumb { opacity:0.5; }
.proj-row.placeholder .proj-body h4 { color:var(--soft); }
/* Draft preview (owner-only — never shown to a real visitor): same dimmed
   treatment as "Coming soon", but the tag is dashed to read as private/WIP
   rather than a public promise. */
.tag-soon.tag-draft { border-style:dashed; }
@media (prefers-reduced-motion: reduce){ .proj-row { transition:box-shadow .22s ease, border-color .2s; } .proj-row:not(.placeholder):hover { transform:none; } .proj-row:not(.placeholder):hover .proj-arrow .ar { transform:translateX(4px); } }

/* Dark mode: lift the resource-list contrast (blurb, "Coming soon" tag,
   thumbnail label, placeholder titles all read too faint on the dark surface). */
html[data-theme="dark"] .proj-body .blurb { color:var(--ink-2); }
html[data-theme="dark"] .proj-body .resource { color:var(--accent-ink); }
html[data-theme="dark"] .proj-thumb .ph { color:color-mix(in srgb,var(--accent) 70%,var(--ink-2)); }
html[data-theme="dark"] .proj-row.placeholder .proj-thumb { opacity:0.72; }
html[data-theme="dark"] .tag-soon {
  background:color-mix(in srgb,var(--surface) 65%,var(--bg));
  color:var(--ink); border-color:color-mix(in srgb,var(--ink) 28%,var(--line));
}

/* ---------------------------------------------------------------------------
   Contact
   --------------------------------------------------------------------------- */
.contact { padding:70px 0 50px; }
.contact .wrap { display:grid; grid-template-columns:0.9fr 1.1fr; gap:60px; }
.contact .intro .eyebrow { margin-bottom:14px; }
.contact .intro h2 { font-size:clamp(1.9rem,4vw,2.8rem); font-weight:600; margin-bottom:18px; }
.contact .intro h2 .accent-text { color:var(--accent-text); }
.contact .intro p, .contact .intro .lede-contact { color:var(--ink-2); max-width:40ch; }
.contact .intro .mail { margin-top:22px; font-weight:600; }
.contact .intro .mail a { color:var(--accent-text); border-bottom:1px solid transparent; padding-bottom:2px; }
.contact .intro .mail a:hover { border-color:var(--accent); }

.form { background:var(--surface); border:1px solid var(--line); border-radius:18px; padding:28px; display:grid; gap:16px; }
.form .row { display:grid; grid-template-columns:1fr 1fr; gap:16px; }
.field { display:grid; gap:7px; }
.field label { font-size:0.82rem; font-weight:600; color:var(--ink-2); }
.field input, .field select, .field textarea { font-family:inherit; font-size:1rem; color:var(--ink); background:var(--bg); border:1.5px solid var(--line); border-radius:10px; padding:12px 14px; width:100%; transition:border-color .15s, box-shadow .15s; }
.field input:focus, .field select:focus, .field textarea:focus { outline:none; border-color:var(--accent); box-shadow:0 0 0 3px var(--accent-soft); }
.field textarea { resize:vertical; min-height:110px; }
.field select { appearance:none; }
.form .submit { font-weight:600; font-size:0.95rem; background:var(--accent); color:var(--on-accent); border:0; border-radius:10px; padding:14px; cursor:pointer; transition:background .2s, opacity .2s; }
.form .submit:hover { background:var(--accent-2); }

/* Gate the contact "Send" button until every required field is valid — pure CSS,
   no JavaScript. This dims the button and blocks clicks while any field is
   incomplete or invalid; the fields' own `required`/`type=email` still stop a
   real submit. ".submit" only exists on the contact form, so login/reset are
   unaffected. */
.form:has(:invalid) .submit { opacity:0.4; pointer-events:none; }

.form-flash { border-radius:var(--radius-sm); padding:13px 16px; font-size:0.92rem; font-weight:500; border:1px solid transparent; }
.form-flash.is-success { background:color-mix(in srgb,var(--ok) 16%,var(--surface)); color:var(--ok); border-color:color-mix(in srgb,var(--ok) 40%,var(--line)); }
.form-flash.is-error { background:color-mix(in srgb,var(--warn) 16%,var(--surface)); color:var(--warn); border-color:color-mix(in srgb,var(--warn) 40%,var(--line)); }

/* Owner-only warning strip when data/store.json exists but can't be read
   (see store_corrupt() in includes/store.php + the banner in header.php). */
.store-corrupt-banner { background:var(--warn); color:#fff; padding:12px 20px; text-align:center; font-size:0.92rem; font-weight:600; }
.hp { position:absolute; left:-9999px; width:1px; height:1px; overflow:hidden; }

/* ---------------------------------------------------------------------------
   Footer
   --------------------------------------------------------------------------- */
.foot { border-top:1px solid var(--line); margin-top:30px; }
.foot .wrap { display:flex; align-items:center; gap:20px; flex-wrap:wrap; padding-block:26px; font-size:0.86rem; color:var(--soft); }
.foot .spacer { flex:1; }
.foot a:hover { color:var(--ink); }
.foot .accent-text { color:var(--accent-text); font-weight:600; }
.foot .social-link { display:inline-grid; place-items:center; width:34px; height:34px; border-radius:8px; color:var(--soft); border:1px solid var(--line); transition:color .15s, border-color .15s; }
.foot .social-link:hover { color:var(--accent-text); border-color:var(--accent); }
.admin-link { font-size:0.82rem; color:var(--faint); border-bottom:1px dotted var(--line); transition:color .15s, border-color .15s; }
.admin-link:hover { color:var(--accent-text); border-color:var(--accent); }
.admin-flag { font-family:var(--f-display); font-size:0.72rem; font-weight:700; letter-spacing:0.04em; text-transform:uppercase; color:var(--accent-text); background:var(--accent-soft); border:1px solid color-mix(in srgb,var(--accent) 30%,var(--line)); padding:4px 10px; border-radius:999px; }

/* ===========================================================================
   RESOURCE DETAIL PAGE
   =========================================================================== */
.back { display:inline-flex; align-items:center; gap:8px; margin-top:28px; font-size:0.88rem; font-weight:600; color:var(--soft); transition:color .2s; }
.back:hover { color:var(--accent-text); }

.detail-head { padding:26px 0 36px; }
.detail-head .resource-line { display:flex; align-items:center; gap:12px; margin-bottom:18px; }
.detail-head .resource-line .val { font-size:0.82rem; font-weight:700; letter-spacing:0.1em; text-transform:uppercase; color:var(--accent-text); }
.detail-head h1 { font-size:clamp(2.4rem,5.5vw,4rem); font-weight:600; letter-spacing:-0.03em; max-width:18ch; }
.detail-head .summary { margin-top:22px; font-size:1.18rem; color:var(--ink-2); max-width:60ch; }
.specbar { margin-top:34px; display:grid; grid-template-columns:repeat(4,1fr); background:var(--surface); border:1px solid var(--line); border-radius:16px; overflow:hidden; }
.specbar .spec { padding:18px 22px; border-inline-end:1px solid var(--line); }
.specbar .spec:last-child { border-inline-end:0; }
.specbar .spec .spec-label { font-size:0.66rem; font-weight:600; letter-spacing:0.14em; text-transform:uppercase; color:var(--label-ink); margin-bottom:6px; }
.specbar .spec .spec-value { font-size:1rem; font-weight:500; color:var(--ink-2); }

/* Skills strip under the spec bar — cross-cutting competencies the project
   demonstrates, deliberately kept out of the ADDIE arc (it's about the maker,
   not the process). Reuses the ul.skills chip styling. */
.detail-skills { margin-top:16px; padding:2px 22px 0; display:flex; align-items:center; gap:8px 14px; flex-wrap:wrap; }
.detail-skills .ds-label { flex:none; font-size:0.66rem; font-weight:600; letter-spacing:0.14em; text-transform:uppercase; color:var(--label-ink); }

.plate { aspect-ratio:var(--ar-video); background:var(--accent-soft); background-image:repeating-linear-gradient(135deg, transparent 0 18px, color-mix(in srgb,var(--accent) 6%,transparent) 18px 19px); border:1px solid var(--line); border-radius:18px; display:grid; place-items:center; margin-top:8px; overflow:hidden; position:relative; }
.plate img { width:100%; height:100%; object-fit:cover; display:block; }

.prose { padding:58px 0 20px; }

/* ---------------------------------------------------------------------------
   ADDIE jump-nav — slim sticky sub-bar under the top bar (resource detail only).
   Lists only the phases that have content; scroll-spy adds .is-active.
   --------------------------------------------------------------------------- */
.addie-nav { position:sticky; top:var(--stick-nav); z-index:40; background:color-mix(in srgb, var(--surface) 88%, transparent); backdrop-filter:blur(12px); border-bottom:1px solid var(--line); }
.addie-nav .wrap { display:flex; align-items:center; gap:20px; }
.addie-nav .addie-nav-label { flex:none; font-size:0.64rem; font-weight:600; letter-spacing:0.14em; text-transform:uppercase; color:var(--faint); font-family:var(--f-mono); }
.addie-nav ul { list-style:none; margin:0; padding:0; display:flex; gap:2px; overflow-x:auto; scrollbar-width:none; }
.addie-nav ul::-webkit-scrollbar { display:none; }
.addie-nav a { display:flex; align-items:center; gap:9px; padding:13px 14px; color:var(--soft); font-weight:600; font-size:0.9rem; white-space:nowrap; position:relative; transition:color .18s; }
.addie-nav a .an-letter { flex:none; font-family:var(--f-mono); font-size:0.7rem; font-weight:700; width:22px; height:22px; border-radius:6px; display:grid; place-items:center; background:var(--bg); border:1px solid var(--line); color:var(--faint); transition:background .18s, border-color .18s, color .18s; }
.addie-nav a::after { content:""; position:absolute; left:14px; right:14px; bottom:0; height:2px; border-radius:2px 2px 0 0; background:var(--accent); transform:scaleX(0); transform-origin:left; transition:transform .2s ease; }
.addie-nav a:hover { color:var(--ink); }
.addie-nav a:hover .an-letter { border-color:var(--accent); color:var(--accent-text); }
.addie-nav a.is-active { color:var(--accent-text); }
.addie-nav a.is-active .an-letter { background:var(--accent); border-color:var(--accent); color:var(--on-accent); }
.addie-nav a.is-active::after { transform:scaleX(1); }

/* Land jump targets below both sticky bars (top bar + ADDIE nav). */
[id^="s-"], [id^="phase-"], #full-resource { scroll-margin-top:var(--stick-anchor); }

/* ---------------------------------------------------------------------------
   ADDIE phase dividers — centred chapter markers between phases. The jump-nav
   bar links to these. Letter chip echoes the bar; the wrap-up divider is
   letter-less (--plain) to signal it sits outside the ADDIE arc.
   --------------------------------------------------------------------------- */
.phase-divider { display:flex; align-items:center; gap:24px; margin:64px 0 8px; }
.phase-divider .pd-rule { flex:1; height:2px; border-radius:2px; background:color-mix(in srgb, var(--ink) 20%, transparent); }
.phase-divider .pd-label { display:inline-flex; align-items:center; gap:13px; flex:none; }
.phase-divider .pd-letter { flex:none; font-family:var(--f-mono); font-size:0.82rem; font-weight:700; width:30px; height:30px; border-radius:8px; display:grid; place-items:center; background:var(--accent-soft); color:var(--accent-ink); }
.phase-divider .pd-name { font-family:var(--f-display); font-weight:600; font-size:1.5rem; letter-spacing:-0.02em; color:var(--ink); }
/* Wrap-up divider: quieter, no letter chip, eyebrow-styled label + finer rule. */
.phase-divider--plain { margin-top:56px; }
.phase-divider--plain .pd-rule { height:1px; background:color-mix(in srgb, var(--ink) 12%, transparent); }
.phase-divider--plain .pd-name { font-family:var(--f-sans); font-size:0.74rem; font-weight:600; letter-spacing:0.16em; text-transform:uppercase; color:var(--soft); }
/* A phase divider that opens a prose block shouldn't sit under a doubled rule. */
.prose .wrap > .phase-divider:first-child { margin-top:8px; }
.phase-divider + .detail-section { border-top:0; padding-top:20px; }
.detail-section { display:grid; grid-template-columns:240px 1fr; gap:44px; padding:34px 0; border-top:1px solid var(--line); }
.detail-section:first-child { border-top:0; padding-top:0; }
.detail-section .section-head { position:sticky; top:var(--stick-head); align-self:start; }
.detail-section .section-head h2 { font-size:1.4rem; font-weight:600; }
.detail-section .section-head h2 .accent-text { color:var(--accent-text); }
.detail-section .section-body { font-size:1.08rem; color:var(--ink-2); max-width:64ch; }
.detail-section .section-body p { margin:0 0 14px; }
.detail-section .section-body p:last-child { margin-bottom:0; }
.detail-section .section-body strong { color:var(--ink); }

ul.clean, ol.clean { list-style:none; margin:0; padding:0; display:grid; gap:13px; }
ul.clean li, ol.clean li { display:grid; grid-template-columns:auto 1fr; gap:14px; align-items:baseline; }
ul.clean li::before, ol.clean li::before { content:""; width:7px; height:7px; border-radius:2px; background:var(--accent); transform:translateY(-2px) rotate(45deg); }
ul.skills { list-style:none; margin:0; padding:0; display:flex; flex-wrap:wrap; gap:9px; }
ul.skills li { font-size:0.86rem; font-weight:600; color:var(--accent-ink); background:var(--accent-soft); border:1px solid color-mix(in srgb,var(--accent) 18%,var(--line)); padding:8px 14px; border-radius:8px; }

.swatches { display:flex; flex-wrap:wrap; gap:14px; }
.swatch { width:96px; }
.swatch .chip { height:62px; border-radius:10px; border:1px solid color-mix(in srgb,var(--ink) 12%,transparent); }
.swatch .hex { font-size:0.74rem; font-weight:600; color:var(--soft); margin-top:8px; font-variant-numeric:tabular-nums; font-family:var(--f-mono); }

/* ---- Visual style section: labeled colors + labeled type samples --------- */
.vstyle-group + .vstyle-group { margin-top:28px; }
.vstyle-label { display:block; font-size:0.68rem; font-weight:700; letter-spacing:0.14em; text-transform:uppercase; color:var(--faint); font-family:var(--f-mono); margin-bottom:14px; }
.swatch-label { font-size:0.78rem; font-weight:600; color:var(--ink-2); margin-bottom:8px; }
.font-samples { display:flex; flex-wrap:wrap; gap:18px; }
.font-sample { width:180px; padding:16px; border:1px solid var(--line); border-radius:var(--radius-sm); background:var(--surface); }
.font-sample-glyph { font-size:2.2rem; line-height:1; color:var(--ink); }
.font-sample-name { margin-top:10px; font-size:0.74rem; font-weight:600; color:var(--soft); }
/* Type-style box: Aa (at its true size) on the left; the specific tag + px size
   stacked to its right; family name below. The general label is the group header.
   The Aa row is a FIXED height per group (--fs-top-h, set to the group's largest
   style), so the tag/size and name line up across boxes — only the Aa changes. */
/* TOP-aligned, not bottom. Bottom alignment sat the tag on a common baseline
   across boxes, but inside a box it left the Aa's top floating anywhere from
   6px above to 13px below the tag beside it, depending on the style's size.
   Aligning tops fixes the in-box relationship AND still lines the tags up
   across boxes, because they now all start at the same y. */
.fs-top { display:flex; align-items:flex-start; gap:12px; height:var(--fs-top-h, 2.6rem); }
.fs-meta { display:flex; flex-direction:column; line-height:1.15; }
.fs-tag { font-size:0.9rem; font-weight:700; color:var(--ink); font-family:var(--f-display); }
.fs-size { font-family:var(--f-mono); font-size:0.68rem; font-weight:500; color:var(--faint); }
/* On phones, fit two type-style boxes per line (a 3-item Header row would
   otherwise cram). The groups + row are forced full-width so a real 2-column
   grid can resolve (a % width wouldn't — the group is shrink-to-fit). Drop the
   bracket connectors (they don't map onto a grid); long names wrap. */
@media (max-width:520px) {
  /* Type styles on phones: a uniform 2-per-row grid. Every style box is one
     equal-width cell — whether it's a solo-label box or one item in a group —
     so boxes always align 2-across instead of stacking full-width. Selectors
     are extra-specific to win over the base .font-samples / .vstyle-conn-* rules
     that appear later in the file. */
  .vstyle-group .font-samples {
    display:grid; grid-template-columns:minmax(0,1fr) minmax(0,1fr);
    gap:18px 14px; align-items:start;
  }
  .font-samples > .vstyle-conn-group,
  .font-samples > .font-sample { width:auto; min-width:0; margin:0; align-items:stretch; }
  .font-samples .font-sample { width:auto; min-width:0; }
  /* Solo-label group: label above its own box, left-aligned, wraps freely.
     A GROUP of 2+ keeps the centred label + bracket (below). */
  .font-samples > .vstyle-conn-group:not(.vstyle-conn-group--multi) .vstyle-conn-head { align-items:flex-start; }
  .font-samples > .vstyle-conn-group:not(.vstyle-conn-group--multi) .vstyle-conn-stem { display:none; }
  .font-samples > .vstyle-conn-group .vstyle-conn-label { white-space:normal; }
  /* A multi-font group spans the full row and keeps its own inner 2-col grid. */
  .font-samples > .vstyle-conn-group--multi { grid-column:1 / -1; }
  .font-samples .vstyle-conn-row--fonts { display:grid; grid-template-columns:repeat(min(var(--n,2), 2), minmax(0,1fr)); gap:14px; width:100%; }
  /* The bracket, kept on phones. It was dropped here because the row becomes a
     grid and the desktop rule's fixed 90px insets no longer land on anything.
     With --n (the item count, emitted by Resource.php) the outer cell centres
     are exact: (100% - (n-1)*gap) / 2n from each edge. */
  .font-samples .vstyle-conn-row--fonts::before {
    left:calc((100% - (min(var(--n,2), 2) - 1) * 14px) / (2 * min(var(--n,2), 2)));
    right:calc((100% - (min(var(--n,2), 2) - 1) * 14px) / (2 * min(var(--n,2), 2)));
  }
  /* Colors on phones: a 3-per-row grid. Standalone swatches are one cell each; a
     shared-label group (e.g. the 3 Secondary Accents) spans the full row and
     keeps its swatches together under one label. */
  .vstyle-group .swatches { display:grid; grid-template-columns:repeat(3, minmax(0,1fr)); gap:16px 14px; align-items:start; }
  /* Every swatch fills its grid cell — the base `.swatch { width:96px }` would
     otherwise leave it left-aligned in a wider cell, putting the swatch's
     centre ~30px off the cell centre the bracket's calc() aims at. The `>`
     selector alone missed the ones nested inside a connector row. */
  .swatches .swatch { width:auto; min-width:0; }
  .swatches > .vstyle-conn-group { grid-column:1 / -1; }
  .swatches .vstyle-conn-row--colors { display:grid; grid-template-columns:repeat(min(var(--n,3), 3), minmax(0,1fr)); gap:14px; width:100%; }
  /* Same treatment as the type bracket above: --n makes the rule end on the
     centre of the first and last swatch whatever the count. */
  .swatches .vstyle-conn-row--colors::before {
    left:calc((100% - (min(var(--n,3), 3) - 1) * 14px) / (2 * min(var(--n,3), 3)));
    right:calc((100% - (min(var(--n,3), 3) - 1) * 14px) / (2 * min(var(--n,3), 3)));
  }
}

/* ---- Bracket-grouped swatches / type samples: 2+ entries sharing one label
   get a single centered label wired down to each item's top-center with an
   orthogonal connector (echoes the node-diagram in the site's own logo mark). */
.swatches, .font-samples { align-items:flex-end; }
.vstyle-conn-group { display:flex; flex-direction:column; align-items:center; }
.vstyle-conn-head { display:flex; flex-direction:column; align-items:center; }
.vstyle-conn-label { font-size:0.78rem; font-weight:600; color:var(--ink-2); margin-bottom:8px; white-space:nowrap; }
.vstyle-conn-stem { width:1px; height:14px; background:var(--conn-line); }
.vstyle-conn-row { position:relative; display:flex; gap:14px; padding-top:14px; }
.vstyle-conn-row::before { content:""; position:absolute; top:0; height:1px; background:var(--conn-line); }
.vstyle-conn-row--colors::before { left:48px; right:48px; }
.vstyle-conn-row--fonts::before { left:90px; right:90px; }
.vstyle-conn-row .swatch, .vstyle-conn-row .font-sample { position:relative; }
.vstyle-conn-row .swatch::before, .vstyle-conn-row .font-sample::before { content:""; position:absolute; top:-14px; left:50%; width:1px; height:14px; background:var(--conn-line); transform:translateX(-50%); }

.feature { padding:40px 0; }
.feature .feature-head { display:flex; align-items:baseline; gap:12px; margin-bottom:24px; }
.feature .feature-head h2 { font-size:clamp(1.6rem,3.2vw,2.2rem); font-weight:600; }
.feature .feature-head h2 .accent-text { color:var(--accent-text); }
.feature .feature-head .note { font-size:0.78rem; color:var(--faint); font-weight:600; font-family:var(--f-mono); }

/* ---- Storyboards table (rendered by table.js — display only) ---- */
.tbl-scroll { overflow-x:auto; }
.sb-table { width:100%; border-collapse:collapse; font-size:0.95rem; background:var(--surface); border:1px solid var(--line); border-radius:14px; overflow:hidden; min-width:640px; }
.sb-table th, .sb-table td { text-align:start; padding:14px 16px; border-bottom:1px solid var(--line); border-inline-end:1px solid var(--line); vertical-align:top; }
.sb-table th:last-child, .sb-table td:last-child { border-inline-end:0; }
.sb-table thead th, .sb-table tr:first-child th { background:var(--accent-soft); font-size:0.66rem; font-weight:700; letter-spacing:0.1em; text-transform:uppercase; color:var(--accent-ink); }
.sb-table tbody td:first-child, .sb-table tr td:first-child { font-weight:600; color:var(--accent-text); white-space:nowrap; }
.sb-table tr:last-child td { border-bottom:0; }

/* ---- Carousel (rendered by media.js) ---- */
/* Skip link. Moved off-screen with transform rather than display:none or
   visibility:hidden — both of those remove it from the tab order, which is the
   one thing it exists to be in. inset-inline-start so it lands on the correct
   edge in RTL. */
.skip-link { position:absolute; top:0; inset-inline-start:0; z-index:200;
  transform:translateY(-130%); transition:transform .15s ease;
  background:var(--surface); color:var(--ink); text-decoration:none;
  border:2px solid var(--accent); border-start-start-radius:0; border-end-end-radius:var(--radius-sm);
  padding:10px 18px; font-weight:650; font-size:0.92rem; }
.skip-link:focus { transform:translateY(0); }
@media (prefers-reduced-motion:reduce) { .skip-link { transition:none; } }
.bld-co-alt { flex:1 1 auto; min-width:0; font-size:.82rem; padding:5px 8px; }
.sb-actions { display:flex; justify-content:center; margin-top:14px; }
.sb-download-btn { font-size:0.85rem; }
.carousel-empty { border:1px dashed var(--line); border-radius:var(--radius); padding:40px; text-align:center; color:var(--soft); background:var(--bg); }
.carousel-empty code { display:inline-block; margin-top:10px; font-family:var(--f-mono); font-size:0.82rem; background:var(--surface); border:1px solid var(--line); padding:6px 12px; border-radius:8px; color:var(--accent-text); }
/* Peek carousel. --car-slide is the CURRENT slide's share of the stage width;
   the neighbours occupy the remainder, half on each side, clipped by the stage.
   It is also what sets the stage's HEIGHT: slides are 16:9, so 62% width means
   62% of the old height — the carousel used to stand as tall as the resource
   embed above it, which gave a strip of screenshots the same weight as the work
   itself. media.js reads this property to compute the track offset, so this
   declaration is the single source of truth and a skin can retune it. */
.carousel-stage { --car-slide:62%; --car-side-scale:.86; position:relative; border-radius:var(--radius); overflow:hidden; border:1px solid var(--line); background:var(--bg); }
.carousel-track { display:flex; align-items:center; transition:transform .45s cubic-bezier(.22,.61,.36,1); }
/* The scale is visual only — it never changes the flex layout, so the track
   maths stays a function of --car-slide alone and the stage height is set by
   the current slide rather than wobbling as neighbours grow and shrink. */
.carousel-slide { flex:0 0 var(--car-slide); margin:0; aspect-ratio:var(--ar-video); display:grid; place-items:center;
  transform:scale(var(--car-side-scale)); opacity:.45;
  transition:transform .45s cubic-bezier(.22,.61,.36,1), opacity .45s ease; }
.carousel-slide.is-current { transform:scale(1); opacity:1; }
.carousel-slide img { width:100%; height:100%; object-fit:cover; }
/* One image has no neighbours to make room for, so it takes the full stage. */
.carousel-stage.is-single { --car-slide:100%; --car-side-scale:1; }
.carousel-arrow { position:absolute; top:50%; transform:translateY(-50%); width:44px; height:44px; border-radius:10px; border:1.5px solid var(--line); background:color-mix(in srgb,var(--surface) 88%,transparent); backdrop-filter:blur(6px); color:var(--ink); font-size:1.1rem; cursor:pointer; display:grid; place-items:center; transition:border-color .2s,color .2s; }
.carousel-arrow:hover { border-color:var(--accent); color:var(--accent-text); }
.carousel-arrow.prev { inset-inline-start:14px; }
.carousel-arrow.next { inset-inline-end:14px; }
@media (max-width:760px) { .carousel-stage { --car-slide:84%; --car-side-scale:.9; } }
@media (prefers-reduced-motion:reduce) { .carousel-track, .carousel-slide { transition:none; } }
.carousel-dots { display:flex; gap:8px; justify-content:center; margin-top:16px; }
.carousel-dot { width:9px; height:9px; border-radius:50%; border:0; padding:0; cursor:pointer; background:var(--line); transition:background-color .2s, transform .2s; }
.carousel-dot.is-on { background:var(--accent); transform:scale(1.25); }
.carousel-counter { text-align:center; margin-top:10px; font-family:var(--f-mono); font-size:0.78rem; color:var(--faint); }
.carousel-upload { display:flex; justify-content:center; margin-top:14px; }
.carousel-add-btn { font-size:0.85rem; }

/* ---- Full resource (rendered by media.js) ---- */
.fr-controls { display:flex; gap:10px; flex-wrap:wrap; margin-bottom:12px; }
.fr-hint { font-size:0.82rem; color:var(--faint); margin-bottom:16px; }
.fr-frame { position:relative; aspect-ratio:var(--ar-video); border-radius:18px; overflow:hidden; border:1px solid var(--line); background:var(--bg); }
.fr-frame iframe { width:100%; height:100%; border:0; display:block; }
/* A PDF gets a page-shaped frame, not a widescreen one — a portrait page in a
   16:9 box is what made the browser's own viewer blow the page up. Capped
   against the viewport so a long document never pushes the rest of the page
   off-screen on a laptop. */
.fr-frame.is-pdf { aspect-ratio:1 / 1.2; max-height:82vh; }
@media (max-width:700px) { .fr-frame.is-pdf { aspect-ratio:1 / 1.35; } }
/* A self-hosted video plays in a real <video>, not a frame — same box, so the
   section keeps its shape whichever way a resource is presented. */
.fr-frame video { width:100%; height:100%; display:block; background:#000; object-fit:contain; }
/* Link-only: for things no browser renders in place (.pptx) and for hosts that
   refuse to be framed. An honest button beats an empty rectangle. */
.fr-frame.is-download { display:grid; place-items:center; background:var(--accent-soft); background-image:repeating-linear-gradient(135deg, transparent 0 18px, color-mix(in srgb,var(--accent) 6%,transparent) 18px 19px); }
.fr-download { text-align:center; padding:24px; }
.fr-frame.is-empty { display:grid; place-items:center; background:var(--accent-soft); background-image:repeating-linear-gradient(135deg, transparent 0 18px, color-mix(in srgb,var(--accent) 6%,transparent) 18px 19px); }

/* ===========================================================================
   LOGIN PAGE
   =========================================================================== */
.login { padding:64px 0 24px; min-height:60vh; }
.login-card { max-width:430px; margin:0 auto; background:var(--surface); border:1px solid var(--line); border-radius:var(--radius); box-shadow:0 1px 3px rgba(22,22,31,0.05); padding:36px 34px; }
.login-card h1 { font-size:1.6rem; margin:0 0 6px; }
.login-note { color:var(--soft); margin:0 0 24px; font-size:0.95rem; }
.login-card .form { background:transparent; border:0; padding:0; gap:16px; }
.login-or { display:flex; align-items:center; gap:14px; margin:22px 0; color:var(--faint); font-size:0.78rem; font-weight:600; letter-spacing:0.08em; text-transform:uppercase; }
.login-or::before, .login-or::after { content:""; flex:1; height:1px; background:var(--line); }
.biometric-btn { width:100%; justify-content:center; padding:14px; font-size:0.98rem; gap:11px; }
.biometric-btn svg { width:20px; height:20px; }
.login-links { display:flex; justify-content:space-between; align-items:center; margin-top:18px; font-size:0.86rem; }
.login-links a { color:var(--soft); }
.login-links a:hover { color:var(--accent-text); }
.text-link { background:none; border:0; padding:0; cursor:pointer; font-family:inherit; font-size:inherit; color:var(--soft); }
.text-link:hover { color:var(--accent-text); }

/* ===========================================================================
   SETTINGS PANEL (owner-only) — Phase 2 shell, styled now
   =========================================================================== */
.settings-overlay { position:fixed; inset:0; z-index:90; background:rgba(15,15,25,0.45); backdrop-filter:blur(2px); display:none; }
.settings-overlay.open { display:block; }
/* The panel itself always docks to the physical right edge of the viewport
   and slides in from there, regardless of language — that's a fixed piece of
   app chrome (like a browser dev-tools panel), not something reading
   direction should flip. Its CONTENT, though, is now fully localized
   (including RTL) — see the [dir="rtl"] block near the end of this file. */
.settings-panel { position:fixed; top:0; right:0; height:100%; width:380px; max-width:92vw; z-index:91; background:var(--surface); border-left:1px solid var(--line); box-shadow:-20px 0 50px -20px rgba(0,0,0,0.3); transform:translateX(100%); transition:transform .28s cubic-bezier(.22,.61,.36,1); display:flex; flex-direction:column; }
.settings-panel.open { transform:translateX(0); }
.settings-panel .sp-head { display:flex; align-items:center; justify-content:space-between; padding:20px 22px; border-bottom:1px solid var(--line); }
.settings-panel .sp-head h2 { font-size:1.15rem; }
.settings-panel .sp-body { padding:22px; overflow-y:auto; display:grid; gap:26px; flex:1 1 auto; min-height:0; align-content:start; }

/* ===========================================================================
   Responsive
   =========================================================================== */
@media (max-width:860px) {
  .hero .wrap { grid-template-columns:1fr; gap:26px; }
  /* Compact circular avatar, top-left — a profile chip that doesn't shove the
     headline down the page the way a full 220px block did. */
  .headshot { max-width:132px; width:132px; order:-1; justify-self:start; border-radius:50%; aspect-ratio:var(--ar-square); }
  .contact .wrap { grid-template-columns:1fr; gap:34px; }
  .proj-row { flex-direction:column; }
  .proj-thumb { width:100%; max-width:none; aspect-ratio:var(--ar-video); border-inline-end:0; border-bottom:1px solid var(--line); }
  .tabs { flex-wrap:nowrap; overflow-x:auto; -webkit-overflow-scrolling:touch; padding-bottom:4px; scrollbar-width:none; }
  .tabs::-webkit-scrollbar { display:none; }
  .tabs .tab { flex:0 0 auto; }
  .specbar { grid-template-columns:1fr 1fr; }
  .specbar .spec:nth-child(2) { border-inline-end:0; }
  .specbar .spec:nth-child(1), .specbar .spec:nth-child(2) { border-bottom:1px solid var(--line); }
  .detail-section { grid-template-columns:1fr; gap:14px; }
  .detail-section .section-head { position:static; }
}

/* ---- Collapse the top bar into a hamburger menu ------------------------------
   Fires early enough that the brand + tools + CTA never overflow / cause the
   horizontal scroll the full bar did. Tools (About, language, theme, settings)
   drop into a panel under the bar; the CTA + hamburger stay in the bar. */
@media (max-width:760px) {
  .brand .role { display:none; }
  .top .hamburger { display:grid; }
  .top .wrap { gap:10px; }
  .cta { padding:9px 16px; }
  .topbar-tools {
    display:none;
    position:absolute; top:calc(100% + 9px); right:0;
    flex-direction:row; align-items:center; justify-content:space-between; gap:14px;
    min-width:min(280px, 86vw);
    padding:10px 14px; background:var(--surface);
    border:1px solid var(--line); border-radius:14px;
    box-shadow:0 18px 44px rgba(22,22,31,0.18);
  }
  .topbar-tools[data-open="true"] { display:flex; }
  .topbar-tools .nav-link { order:-1; padding:10px 12px; border-radius:10px; font-size:1rem; }
  .topbar-tools .nav-link:hover { background:var(--bg); }
  .topbar-toggles { gap:8px; }
  /* Findings: reveal the toggle (JS has already collapsed the panel). */
  .findings-toggle { display:flex; }
}
@media (max-width:520px) {
  .form .row { grid-template-columns:1fr; }
  .brand .role { display:none; }
  .addie-nav .addie-nav-label { display:none; }
  .addie-nav a .an-label { display:none; }
  .addie-nav a { padding:11px 10px; }
  /* Phone gets a tighter gap under the bars, not a shorter stack — the nav is
     the same height with its labels hidden. Expressed as a delta off the token
     so a skin only ever overrides --stick-anchor once. */
  [id^="s-"], [id^="phase-"], #full-resource { scroll-margin-top:calc(var(--stick-anchor) - 14px); }
  .phase-divider { gap:16px; margin:44px 0 6px; }
  .phase-divider .pd-name { font-size:1.25rem; }
}

/* ===========================================================================
   RESOURCE BUILDER (owner-only) — lives inside the Settings panel
   =========================================================================== */

/* The panel grows when the builder is active so the form has room to breathe. */
.settings-panel { transition:transform .28s cubic-bezier(.22,.61,.36,1), width .32s cubic-bezier(.22,.61,.36,1); }
.settings-panel[data-builder-active="true"] { width:640px; }

/* Cross-fade between the settings home and the builder form. */
.sp-body { transition:opacity .15s ease; }
.sp-body.bld-fade-out { opacity:0; }
.bld-fade { animation:bldFadeIn .22s ease both; }
.bld-fade-out { opacity:0 !important; transition:opacity .13s ease; }
@keyframes bldFadeIn { from { opacity:0; transform:translateY(4px); } to { opacity:1; transform:none; } }
@media (prefers-reduced-motion:reduce) {
  .settings-panel, .sp-body, .bld-fade { transition:none !important; animation:none !important; }
}

/* ---- Settings-home: the Resources picker block --------------------------- */
.bld-home-block { display:grid; gap:12px; }
.bld-home-block > h3 { font-size:.95rem; }
#bld-resource-picker { display:grid; gap:10px; }
.bld-picker { width:100%; }
.bld-create { justify-self:start; }

/* ---- Builder header (replaces the gear-row contents) --------------------- */
.sp-body.bld-mode { padding-bottom:96px; }      /* clear the sticky save bar */
.bld-head-top { display:flex; align-items:center; justify-content:space-between; gap:12px; width:100%; }
.bld-back { appearance:none; border:0; background:transparent; cursor:pointer; font-family:var(--f-sans); font-size:.92rem; font-weight:600; color:var(--soft); padding:6px 2px; border-radius:8px; transition:color .15s; }
.bld-back:hover { color:var(--accent-text); }
.bld-head-title { margin-top:10px; }
.bld-eyebrow { font-family:var(--f-mono); font-size:.66rem; letter-spacing:.16em; text-transform:uppercase; color:var(--faint); }
.bld-head-name { font-size:1.18rem; margin-top:3px; word-break:break-word; }
.bld-lang-seg button { padding:5px 11px; }
/* Icon-only light/dark control — same sun/moon as the visitor-facing toggle
   (see THEME_ICON in scripts/builder.js). Square so the two sit as a pair. */
.bld-theme-seg-icon button { padding:5px 9px; display:grid; place-items:center; }
.bld-theme-seg-icon svg { width:17px; height:17px; display:block; }

/* Language switcher inside the panel head. The panel covers the top bar, so
   this is the only way to change language while Settings is open — see the
   note in includes/footer.php. Pushed right so the title stays left-aligned
   and the close button stays in its usual corner. */
.settings-panel .sp-head .sp-lang { margin-left:auto; margin-right:10px; }
.settings-panel .sp-head .sp-lang a { padding:5px 11px; font-size:.78rem; }

/* Builder header stacks vertically: back + control on row 1, title below.
   The builder replaces this header's contents wholesale, so the switcher
   above is only present on the Settings HOME screen — which is where the
   Language block itself lives, so it's in the right place either way. */
.settings-panel[data-builder-active="true"] .sp-head { display:block; }

/* In-form layout toggle (Stacked / Tabbed). */
.bld-layout-row { display:flex; align-items:center; justify-content:space-between; gap:12px; margin-bottom:18px; padding-bottom:16px; border-bottom:1px solid var(--hair); }
.bld-layout-label { font-family:var(--f-mono); font-size:.66rem; letter-spacing:.16em; text-transform:uppercase; color:var(--faint); }
.bld-layout-seg button { padding:5px 13px; }

/* ---- Form scaffold ------------------------------------------------------- */
.bld-form { display:grid; gap:26px; }
.bld-section { display:grid; gap:14px; padding-bottom:22px; border-bottom:1px solid var(--hair); }
.bld-form .bld-section:last-child { border-bottom:0; padding-bottom:0; }
.bld-section-title { font-size:.78rem; letter-spacing:.12em; text-transform:uppercase; color:var(--accent-text); font-family:var(--f-sans); font-weight:700; }

.bld-field { display:grid; gap:7px; }
.bld-label { font-size:.86rem; font-weight:600; color:var(--ink-2); display:flex; align-items:center; gap:8px; }
.bld-lang-tag { font-family:var(--f-mono); font-size:.6rem; letter-spacing:.1em; color:var(--accent-text); background:var(--accent-soft); border-radius:5px; padding:2px 5px; }
.bld-hint { font-size:.78rem; color:var(--soft); margin:0; line-height:1.45; }
/* A hint sitting directly under its own label, with no gap above. Used where
   the guidance belongs to the field above it rather than the control below. */
.bld-hint-tight { margin-top:-2px; }
/* A hint that is a caveat, not a nicety (e.g. "this host can't build zips, so
   your images are NOT in the download") — same size, warning color + weight. */
.bld-hint.bld-warn { color:var(--warn); font-weight:600; }

.bld-input { width:100%; font-family:var(--f-sans); font-size:.92rem; color:var(--ink); background:var(--bg); border:1px solid var(--line); border-radius:10px; padding:10px 12px; transition:border-color .15s, box-shadow .15s; }
.bld-input:focus { outline:none; border-color:var(--accent); box-shadow:0 0 0 3px var(--accent-soft); }
.bld-textarea { resize:vertical; line-height:1.5; min-height:84px; }
.bld-select { appearance:none; cursor:pointer; background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%2362636F' stroke-width='3' stroke-linecap='round'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E"); background-repeat:no-repeat; background-position:right 12px center; padding-inline-end:34px; }
/* background-position has no logical "inline-end" value, so RTL needs an
   explicit override to move the chevron to the other side. */
[dir="rtl"] .bld-select { background-position:left 12px center; }
.bld-mono { font-family:var(--f-mono); font-size:.84rem; }
.bld-input.is-locked { color:var(--soft); background:var(--hair); cursor:not-allowed; }
/* Rich-text field: formatting toolbar over a contenteditable editor. */
.bld-rt { display:grid; gap:0; }
.bld-rt-bar { display:flex; flex-wrap:wrap; gap:4px; padding:6px; background:var(--hair); border:1px solid var(--line); border-bottom:0; border-radius:10px 10px 0 0; }
.bld-rt-btn { min-width:30px; height:30px; display:inline-flex; align-items:center; justify-content:center; padding:0 8px; font-family:var(--f-sans); font-size:.9rem; line-height:1; color:var(--ink-2); background:var(--surface); border:1px solid var(--line); border-radius:7px; cursor:pointer; transition:background .12s, color .12s, border-color .12s; }
.bld-rt-btn:hover { color:var(--accent-text); border-color:var(--accent); }
.bld-rt-btn[aria-pressed="true"] { color:var(--on-accent); background:var(--accent); border-color:var(--accent); }
.bld-rt-editor { min-height:96px; line-height:1.5; border-radius:0 0 10px 10px; }
.bld-rt-editor:focus { outline:none; border-color:var(--accent); box-shadow:0 0 0 3px var(--accent-soft); }
.bld-rt-editor p { margin:0 0 .6em; }
.bld-rt-editor p:last-child { margin-bottom:0; }
.bld-rt-editor ul, .bld-rt-editor ol { margin:0 0 .6em; padding-inline-start:1.4em; }
.bld-rt-editor blockquote { margin:0 0 .6em 1.4em; }
.bld-rt-editor a { color:var(--accent-text); }
/* On touch devices, iOS Safari zooms the whole viewport when a control with a
   font-size under 16px is focused — which visually enlarged the fixed Settings
   panel and its Save/Discard footer. Bumping panel controls to 16px on coarse
   pointers stops the zoom (and the footer no longer scales). Desktop keeps the
   more compact .92rem sizing. */
@media (pointer: coarse) {
  .settings-panel input,
  .settings-panel select,
  .settings-panel textarea,
  .settings-panel .bld-input { font-size:16px; }
}

/* ---- List editor --------------------------------------------------------- */
.bld-list { display:grid; gap:8px; }
.bld-list-items { display:grid; gap:8px; }
.bld-list-row, .bld-color-row { display:flex; align-items:center; gap:8px; }
.bld-list-row .bld-input, .bld-color-hex { flex:1; }
.bld-empty { font-size:.82rem; color:var(--faint); margin:0; font-style:italic; }
.bld-icon-btn { appearance:none; flex:0 0 auto; width:34px; height:34px; border-radius:9px; border:1px solid var(--line); background:var(--surface); color:var(--soft); font-size:1.2rem; line-height:1; cursor:pointer; display:grid; place-items:center; transition:color .15s, border-color .15s, background .15s; }
.bld-icon-btn:hover { color:var(--warn); border-color:var(--warn); }
.bld-add { appearance:none; cursor:pointer; font-family:var(--f-sans); font-size:.84rem; font-weight:600; color:var(--accent-text); background:var(--accent-soft); border:0; border-radius:9px; padding:8px 14px; transition:filter .15s; }
.bld-add:hover { filter:brightness(.97); }

/* ---- Color editor -------------------------------------------------------- */
.bld-color-dot { flex:0 0 auto; width:38px; height:34px; padding:0; border:1px solid var(--line); border-radius:9px; background:none; cursor:pointer; }
.bld-color-dot::-webkit-color-swatch-wrapper { padding:3px; }
.bld-color-dot::-webkit-color-swatch { border:0; border-radius:6px; }

/* ---- Image field --------------------------------------------------------- */
.bld-image { display:grid; gap:8px; }
.bld-image-prev { width:100%; aspect-ratio:var(--ar-video); border:1px solid var(--line); border-radius:10px; overflow:hidden; background:repeating-linear-gradient(45deg,var(--hair),var(--hair) 9px,var(--bg) 9px,var(--bg) 18px); display:grid; place-items:center; }
.bld-image-prev img { width:100%; height:100%; object-fit:cover; }
/* A headshot is not 16:9. This preview keeps whatever shape the photo is, in a
   box tall enough to judge it by, instead of letterboxing a portrait. */
.bld-image-prev--free { aspect-ratio:auto; min-height:180px; max-height:280px; padding:8px; }
.bld-image-prev--free img { width:auto; max-width:100%; height:100%; object-fit:contain; }
.bld-image-controls { display:flex; flex-wrap:wrap; gap:8px; align-items:center; }
.bld-image-controls .bld-input { flex:1; min-width:160px; }
.bld-upload-btn { flex:0 0 auto; }
.bld-ph { font-family:var(--f-mono); font-size:.7rem; letter-spacing:.14em; color:var(--faint); display:grid; gap:6px; justify-items:center; text-align:center; padding:0 12px; }
.bld-ph-drop { font-family:var(--f-sans); letter-spacing:0; font-size:.78rem; color:var(--soft); }

/* Drop targets. The dashed outline only appears mid-drag, so the resting
   state of the panel is unchanged — and `pointer-events:none` on the contents
   keeps the drag events on the zone itself rather than on whatever child
   happens to be under the cursor. */
.bld-image-prev { transition:border-color .16s, background-color .16s; }
.bld-image-prev.is-dragover,
.carousel-wrap.is-dragover { border-color:var(--accent); background-color:var(--accent-soft); outline:2px dashed var(--accent); outline-offset:-6px; }
.bld-image-prev.is-dragover > *, .carousel-wrap.is-dragover > * { pointer-events:none; }
.carousel-wrap.is-dragover { border-radius:var(--radius); }

/* ---- Visibility toggles + status badge ----------------------------------- */
.bld-visibility { display:grid; gap:16px; }
.bld-badge-row { display:flex; }
.bld-badge { font-size:.72rem; font-weight:700; letter-spacing:.06em; text-transform:uppercase; padding:5px 11px; border-radius:999px; }
.bld-badge.is-live { color:var(--ok); background:color-mix(in srgb, var(--ok) 14%, transparent); }
.bld-badge.is-soon { color:var(--warn); background:color-mix(in srgb, var(--warn) 14%, transparent); }
.bld-badge.is-draft { color:var(--soft); background:var(--hair); }
.bld-badge.is-revision { color:var(--accent-text); background:var(--accent-soft); }
.bld-badge.is-archiving { color:#c0392b; background:color-mix(in srgb, #c0392b 14%, transparent); }
.bld-badge.is-archived { color:var(--soft); background:var(--hair); }
.bld-badge.is-restoring { color:var(--ok); background:color-mix(in srgb, var(--ok) 14%, transparent); }
.bld-revision-banner { display:grid; gap:10px; padding:14px 16px; border-radius:12px; margin-bottom:16px; background:var(--accent-soft); border:1px solid color-mix(in srgb, var(--accent) 35%, var(--line)); }
.bld-revision-text { margin:0; font-size:.86rem; color:var(--accent-ink); line-height:1.45; }
.bld-revision-actions { display:flex; gap:10px; flex-wrap:wrap; }
.bld-toggle-row { display:flex; align-items:flex-start; justify-content:space-between; gap:14px; }
.bld-toggle-text { display:grid; gap:3px; }
.bld-toggle-label { font-size:.9rem; font-weight:600; color:var(--ink-2); }
.bld-toggle-hint { font-size:.78rem; color:var(--soft); line-height:1.45; }
.bld-switch { flex:0 0 auto; position:relative; cursor:pointer; }
.bld-switch input { position:absolute; opacity:0; width:0; height:0; }
.bld-track { display:block; width:44px; height:26px; border-radius:999px; background:var(--line); transition:background .2s; position:relative; }
.bld-thumb { position:absolute; top:3px; inset-inline-start:3px; width:20px; height:20px; border-radius:50%; background:#fff; box-shadow:0 1px 3px rgba(0,0,0,.3); transition:transform .2s; }
.bld-switch input:checked + .bld-track { background:var(--accent); }
.bld-switch input:checked + .bld-track .bld-thumb { transform:translateX(18px); }
[dir="rtl"] .bld-switch input:checked + .bld-track .bld-thumb { transform:translateX(-18px); }
.bld-switch input:focus-visible + .bld-track { box-shadow:0 0 0 3px var(--accent-soft); }

/* ---- Tabs layout --------------------------------------------------------- */
.bld-form .bld-rail { display:flex; flex-wrap:wrap; gap:6px; margin-bottom:6px; }
.bld-tab { appearance:none; cursor:pointer; font-family:var(--f-sans); font-size:.8rem; font-weight:600; color:var(--soft); background:var(--bg); border:1px solid var(--line); border-radius:999px; padding:7px 13px; transition:all .15s; }
.bld-tab:hover { color:var(--ink-2); border-color:var(--soft); }
.bld-tab[aria-selected="true"] { color:var(--on-accent); background:var(--accent); border-color:var(--accent); }
.bld-pane { display:grid; gap:14px; transition:opacity .13s ease; }
.bld-pane.bld-fade-out { opacity:0; }

/* ---- Storyboard grid ----------------------------------------------------- */
.bld-table { display:grid; gap:10px; }
.bld-table-bar { display:flex; flex-wrap:wrap; gap:6px; }
.bld-table-btn { appearance:none; cursor:pointer; font-family:var(--f-sans); font-size:.76rem; font-weight:600; color:var(--ink-2); background:var(--surface); border:1px solid var(--line); border-radius:8px; padding:6px 10px; transition:border-color .15s, color .15s; }
.bld-table-btn:hover { color:var(--accent-text); border-color:var(--accent); }
/* ---- Backup & Restore list rows ---- */
.bld-backup-list { display:grid; gap:8px; }
.bld-backup-row { display:flex; align-items:center; justify-content:space-between; gap:12px; padding:10px 12px; border:1px solid var(--line); border-radius:10px; background:var(--bg); }
.bld-backup-meta { display:flex; flex-direction:column; gap:2px; min-width:0; }
.bld-backup-time { font-size:.88rem; font-weight:600; color:var(--ink); }
.bld-backup-sub { font-size:.76rem; color:var(--soft); }
.bld-backup-actions { display:flex; gap:6px; flex:none; }
.bld-backup-actions .bld-table-btn { text-decoration:none; }
.bld-table-scroll { overflow-x:auto; border:1px solid var(--line); border-radius:10px; }
.bld-grid { border-collapse:collapse; width:100%; min-width:480px; }
.bld-grid th, .bld-grid td { border:1px solid var(--line); padding:0; vertical-align:top; }
.bld-grid th { background:var(--hair); }
/* Contenteditable storyboard cells (merge-capable editor). */
.bld-grid td.bld-gcell, .bld-grid th.bld-gcell { min-width:96px; padding:8px 9px; font-family:var(--f-sans); font-size:.82rem; color:var(--ink); cursor:text; outline:none; }
.bld-grid th.bld-gcell { font-weight:700; }
.bld-gcell:focus { box-shadow:inset 0 0 0 2px var(--accent); }
.bld-grid .is-sel { background:var(--accent-soft); }

/* ---- Implement / Evaluate: repeatable records ---------------------------- */
/* One card per rollout, per round of measurement. Drawn as a bounded card so
   two rollouts of the same resource never blur into one another. */
.bld-recs-wrap { display:grid; gap:12px; }
.bld-recs { display:grid; gap:14px; }
.bld-rec { display:grid; gap:14px; padding:14px; border:1px solid var(--line); border-radius:12px; background:var(--bg); }
.bld-rec-head { display:flex; align-items:center; justify-content:space-between; gap:10px; }
/* The record name takes the treatment the group title used to have, now that
   the phase header above it already says which phase this is. */
.bld-rec-name { font-family:var(--f-sans); font-size:.78rem; font-weight:700; letter-spacing:.12em; text-transform:uppercase; color:var(--accent-text); }
.bld-rec-sub { font-family:var(--f-sans); font-size:.7rem; font-weight:700; letter-spacing:.14em; text-transform:uppercase; color:var(--label-ink); margin:6px 0 -4px; }
/* Spans the panel and sits last, so it reads as acting on the whole phase
   rather than on the field above it. */
.bld-add-rec { justify-self:stretch; width:100%; text-align:center; padding:11px 14px; border:1px dashed color-mix(in srgb, var(--accent) 40%, var(--line)); background:transparent; }
.bld-add-rec:hover { background:var(--accent-soft); filter:none; }

.bld-daterange { display:flex; gap:10px; flex-wrap:wrap; }
.bld-daterange-part { flex:1 1 150px; display:grid; gap:4px; }
.bld-daterange-label { font-size:.72rem; color:var(--soft); }
.bld-methodpick { display:grid; gap:8px; }

/* ---- Versioned document slot --------------------------------------------- */
.bld-doc { display:grid; gap:10px; padding:12px; border:1px solid var(--line); border-radius:11px; background:var(--surface); }
.bld-doc-current { display:grid; gap:9px; }
.bld-doc-row { display:flex; align-items:center; gap:9px; flex-wrap:wrap; }
.bld-doc-badge { font-size:.62rem; font-weight:700; letter-spacing:.1em; text-transform:uppercase; color:var(--accent-text); background:var(--accent-soft); border-radius:5px; padding:3px 7px; }
.bld-doc-v { font-family:var(--f-mono); font-size:.74rem; font-weight:700; color:var(--ink-2); }
.bld-doc-file { font-family:var(--f-mono); font-size:.76rem; color:var(--soft); overflow-wrap:anywhere; min-width:0; }
.bld-doc-meta { font-size:.74rem; color:var(--faint); }
.bld-doc-note { display:grid; gap:4px; }
.bld-doc-note-label { font-size:.72rem; color:var(--soft); }
.bld-doc-actions { display:flex; gap:8px; flex-wrap:wrap; }
.bld-doc-hist > summary { cursor:pointer; font-size:.78rem; color:var(--accent-text); font-weight:600; }
.bld-doc-old { display:grid; gap:7px; margin-top:9px; }
.bld-doc-oldrow { display:flex; align-items:center; gap:9px; flex-wrap:wrap; padding:8px 10px; border:1px solid var(--line); border-radius:9px; background:var(--bg); }

/* ---- Issues by priority --------------------------------------------------- */
/* Colour is a SECOND channel here, never the only one: the priority is named in
   the cell beside it, chosen from a dropdown, and stored as a value rather than
   read back from the typed word. Ink is pinned per theme because these tints
   stop being backgrounds you can put --ink on. */
.bld-sevgrid td.bld-gcell { vertical-align:middle; }
.bld-sevgrid tr.bld-sev td { background:var(--sev-bg); color:var(--sev-ink); }
tr.sev-critical { --sev-bg:#FDE7E4; --sev-ink:#16161F; }
tr.sev-major    { --sev-bg:#FDF3D6; --sev-ink:#16161F; }
tr.sev-minor    { --sev-bg:#E6F0FC; --sev-ink:#16161F; }
tr.sev-normal   { --sev-bg:transparent; --sev-ink:var(--ink); }
html[data-theme="dark"] tr.sev-critical { --sev-bg:#4A2320; --sev-ink:#F4E9E7; }
html[data-theme="dark"] tr.sev-major    { --sev-bg:#46391A; --sev-ink:#F5EFE2; }
html[data-theme="dark"] tr.sev-minor    { --sev-bg:#1E3350; --sev-ink:#E5EDF7; }
.bld-dv td.bld-gcell { vertical-align:middle; }
.bld-dv .bld-input, .bld-sevgrid .bld-input { font-size:.84rem; padding:6px 10px; }

/* ---- Multi-select chips + per-measure figures ---------------------------- */
.bld-chips { display:flex; flex-wrap:wrap; gap:7px; }
.bld-chip { display:inline-flex; align-items:center; gap:6px; font-size:.82rem; font-weight:600; color:var(--ink-2); background:var(--surface); border:1px solid var(--line); border-radius:999px; padding:6px 12px; cursor:pointer; }
.bld-chip:has(input:checked) { color:var(--accent-ink); background:var(--accent-soft); border-color:color-mix(in srgb, var(--accent) 35%, var(--line)); }
.bld-chip.is-own { color:var(--accent-ink); background:var(--accent-soft); border-color:color-mix(in srgb, var(--accent) 35%, var(--line)); }
.bld-chip-add { border-style:dashed; color:var(--accent-text); background:transparent; }
.bld-chip-x { appearance:none; border:0; background:none; cursor:pointer; color:inherit; font-size:1rem; line-height:1; padding:0 0 0 2px; }
.bld-quant { display:grid; gap:10px; }
.bld-quant-vals { display:grid; gap:8px; }
.bld-quant-row { display:flex; align-items:center; gap:10px; }
.bld-quant-name { flex:1 1 auto; min-width:0; font-size:.84rem; font-weight:600; color:var(--ink-2); }
.bld-quant-row .bld-input { flex:0 0 132px; }

.bld-metwrap { display:grid; gap:10px; }
.bld-choice { display:flex; flex-wrap:wrap; gap:7px; }
.bld-choice-opt { display:inline-flex; align-items:center; gap:6px; font-size:.84rem; font-weight:600; color:var(--ink-2); background:var(--surface); border:1px solid var(--line); border-radius:999px; padding:6px 13px; cursor:pointer; }
.bld-choice-opt:has(input:checked) { color:var(--accent-ink); background:var(--accent-soft); border-color:color-mix(in srgb, var(--accent) 35%, var(--line)); }

/* ---- Sticky save footer -------------------------------------------------- */
.bld-footer { display:none; }
.settings-panel[data-builder-active="true"] .bld-footer { display:flex; align-items:center; flex:none; gap:10px; padding:16px 22px; border-top:1px solid var(--line); background:color-mix(in srgb, var(--surface) 92%, transparent); backdrop-filter:blur(8px); }
/* Primary save stays on ONE line (never wraps) even when cramped on mobile. */
/* The save-time embed warning sits on its own line UNDER the buttons, so the
   footer has to be allowed to wrap for it. flex-basis:100% is what pushes it
   onto that second line rather than squeezing in beside the buttons. */
.settings-panel[data-builder-active="true"] .bld-footer { flex-wrap:wrap; }
.bld-embed-confirm { flex:1 0 100%; margin-top:4px; padding:13px 15px;
  border:1.5px solid var(--accent); border-radius:12px; background:var(--accent-soft); }
.bld-embed-confirm .bec-msg { margin:0 0 8px; font-size:.86rem; line-height:1.45; color:var(--ink-2); }
.bld-embed-confirm .bec-url { display:block; margin-bottom:11px; font-family:var(--f-mono);
  font-size:.74rem; color:var(--soft); overflow-wrap:anywhere; }
.bld-embed-confirm .bec-row { display:flex; gap:8px; flex-wrap:wrap; }
.bld-embed-confirm .bec-row button { flex:1 1 auto; }

.bld-save { flex:1; appearance:none; cursor:pointer; font-family:var(--f-sans); font-size:.95rem; font-weight:700; white-space:nowrap; color:var(--on-accent); background:var(--accent); border:0; border-radius:11px; padding:13px; transition:background .15s; }
.bld-save:hover { background:var(--accent-2); }
.bld-save:disabled { opacity:.6; cursor:default; }
.bld-save-secondary { flex:0 0 auto; appearance:none; cursor:pointer; font-family:var(--f-sans); font-size:.9rem; font-weight:600; color:var(--ink-2); background:transparent; border:1.5px solid var(--line); border-radius:11px; padding:13px 16px; transition:border-color .15s, color .15s; }
.bld-save-secondary:hover { color:var(--accent-text); border-color:var(--accent); }
/* Discard changes: bordered so it clearly reads as a button (still quieter than
   Save via the muted color). It may wrap to two lines when the footer is tight
   on mobile, but the reduced padding keeps its tap area from growing taller than
   the single-line Save/Draft buttons beside it. */
.bld-discard { flex:0 1 auto; min-width:0; appearance:none; cursor:pointer; font-family:var(--f-sans); font-size:.9rem; font-weight:600; line-height:1.15; text-align:center; white-space:normal; color:var(--soft); background:transparent; border:1.5px solid var(--line); border-radius:11px; padding:8px 12px; transition:color .15s, border-color .15s; }
.bld-discard:hover { color:var(--warn); border-color:var(--warn); }
/* Transient confirmation pill (e.g. "Changes discarded"), pinned just above the
   footer inside the Settings panel; fades in/out via .is-in. */
.bld-toast { position:absolute; left:50%; bottom:88px; transform:translate(-50%, 8px); z-index:5; max-width:calc(100% - 44px); padding:10px 16px; border-radius:999px; background:var(--ink); color:var(--surface); font-family:var(--f-sans); font-size:.85rem; font-weight:600; box-shadow:0 8px 24px -10px rgba(0,0,0,.5); opacity:0; pointer-events:none; transition:opacity .2s ease, transform .2s ease; }
.bld-toast.is-in { opacity:.96; transform:translate(-50%, 0); }

/* ---- Save stub (JSON preview) -------------------------------------------- */
.bld-stub-card { display:grid; gap:12px; margin-top:14px; }
.bld-json { font-family:var(--f-mono); font-size:.74rem; line-height:1.5; color:var(--ink-2); background:var(--bg); border:1px solid var(--line); border-radius:10px; padding:14px; overflow:auto; max-height:340px; white-space:pre; }

@media (max-width:680px) {
  .settings-panel[data-builder-active="true"] { width:100%; max-width:100vw; }
}

/* ---- Header controls: EN/ES + Live-preview toggle ------------------------ */
.bld-head-controls { display:flex; align-items:center; gap:10px; }
.bld-preview-toggle { appearance:none; cursor:pointer; font-family:var(--f-sans); font-size:.82rem; font-weight:600; color:var(--soft); background:var(--bg); border:1.5px solid var(--line); border-radius:9px; padding:6px 12px; transition:color .15s, border-color .15s, background .15s; white-space:nowrap; }
.bld-preview-toggle:hover { color:var(--accent-text); border-color:var(--accent); }
.bld-preview-toggle[aria-pressed="true"] { color:var(--on-accent); background:var(--accent); border-color:var(--accent); }

/* ---- Phase headers in the stacked editor --------------------------------- */
.bld-phase-head { display:flex; align-items:center; gap:12px; margin:14px 0 -6px; }
.bld-phase-head:first-child { margin-top:0; }
.bld-phase-head::after { content:""; flex:1; height:1px; background:var(--line); }
.bld-phase-name { flex:none; font-family:var(--f-mono); font-size:.7rem; font-weight:700; letter-spacing:.16em; text-transform:uppercase; color:var(--accent-ink); }

/* ---- Live-preview drawer (opens to the LEFT of the settings panel) -------- */
.bld-preview-panel { position:fixed; top:0; bottom:0; right:640px; width:clamp(340px, 40vw, 640px); z-index:92; background:var(--bg); border-left:1px solid var(--line); box-shadow:-26px 0 60px -34px rgba(0,0,0,.45); display:flex; flex-direction:column; transform:translateX(24px); opacity:0; pointer-events:none; transition:opacity .28s cubic-bezier(.22,.61,.36,1), transform .28s cubic-bezier(.22,.61,.36,1); }
.bld-preview-panel.open { transform:none; opacity:1; pointer-events:auto; }
.bld-preview-head { flex:none; display:flex; align-items:center; justify-content:space-between; gap:12px; padding:14px 18px; border-bottom:1px solid var(--line); background:var(--surface); }
.bld-preview-title { font-family:var(--f-mono); font-size:.68rem; font-weight:700; letter-spacing:.14em; text-transform:uppercase; color:var(--faint); }
.bld-preview-actions { display:flex; align-items:center; gap:8px; }
.bld-preview-btn { appearance:none; cursor:pointer; font-family:var(--f-sans); font-size:.82rem; font-weight:600; color:var(--ink-2); background:var(--bg); border:1.5px solid var(--line); border-radius:9px; padding:6px 12px; transition:color .15s, border-color .15s; }
.bld-preview-btn:hover { color:var(--accent-text); border-color:var(--accent); }
.bld-preview-close { appearance:none; cursor:pointer; width:30px; height:30px; border-radius:8px; border:0; background:transparent; color:var(--soft); font-size:1.4rem; line-height:1; transition:color .15s, background .15s; }
.bld-preview-close:hover { color:var(--ink); background:var(--hair); }
.bld-preview-frame { position:relative; flex:1 1 auto; min-height:0; }
/* Two stacked buffers for double-buffered updates (a reload never flashes the
   preview back to the top). Both stay RENDERED and opaque; the inactive one is
   simply covered by the active one via z-index — a covered iframe can still be
   scrolled into position before it's brought to the front, whereas a
   visibility:hidden iframe cannot (scroll gets deferred until it's shown). */
.bld-preview-iframe { position:absolute; inset:0; width:100%; height:100%; border:0; display:block; background:#fff; z-index:1; }
.bld-preview-iframe.is-active { z-index:2; }
.bld-preview-panel[data-empty="true"] .bld-preview-iframe { display:none; }
.bld-preview-empty { display:none; }
.bld-preview-panel[data-empty="true"] .bld-preview-empty { display:grid; place-items:center; position:absolute; inset:0; padding:40px; text-align:center; color:var(--soft); font-size:.95rem; }
@media (prefers-reduced-motion:reduce) { .bld-preview-panel { transition:none; } }
/* Not enough room for a side-by-side preview — hide the drawer + its toggle. */
@media (max-width:1180px) {
  .bld-preview-panel { display:none; }
  .bld-preview-toggle { display:none; }
}

/* ===========================================================================
   SETTINGS HOME entry blocks + the two new editor screens
   =========================================================================== */
/* Home: each setting is a titled block with a hint and an action. */
.sp-body > .bld-home-block { display:grid; gap:10px; padding-bottom:20px; margin-bottom:20px; border-bottom:1px solid var(--hair); }
.sp-body > .bld-home-block:last-child { border-bottom:0; margin-bottom:0; padding-bottom:0; }
.bld-home-block > h3 { font-size:.98rem; }
.bld-open { justify-self:start; }

/* Language toggle: the second-language select + default-language select only
   make sense once a second language is on, so they're hidden until the
   checkbox is checked — no JS needed for this, :has() does it. */
.bld-lang-block .bld-lang-fields { display:none; }
.bld-lang-block:has(#bld-lang-enabled:checked) .bld-lang-fields { display:grid; gap:14px; margin-top:2px; }

/* ---- Work categories editor --------------------------------------------- */
.bld-cat-list { display:grid; gap:10px; }
.bld-cat-row { display:grid; grid-template-columns:22px 1fr auto; align-items:start; gap:12px; padding:12px; border:1px solid var(--line); border-radius:12px; background:var(--bg); }
.bld-cat-row.dragging { opacity:.55; border-color:var(--accent); box-shadow:0 8px 22px -10px rgba(0,0,0,.35); }
.bld-drag { cursor:grab; color:var(--faint); font-size:1rem; line-height:1.9; user-select:none; text-align:center; }
.bld-drag:active { cursor:grabbing; }
.bld-cat-fields { display:grid; gap:8px; min-width:0; }
.bld-cat-names { display:grid; grid-template-columns:1fr 1fr; gap:8px; }
/* Only one name field when the second language is off (see catRow() in
   scripts/builder.js) — let it use the full width instead of half. */
.bld-cat-names.is-single { grid-template-columns:1fr; }
.bld-cat-meta { display:flex; flex-direction:column; align-items:flex-end; gap:8px; }
.bld-cat-count { font-family:var(--f-mono); font-size:.68rem; letter-spacing:.04em; color:var(--soft); white-space:nowrap; }
.bld-cat-warn { grid-column:1 / -1; margin:2px 0 0; font-size:.78rem; color:var(--warn); }
.bld-cat-move { grid-column:1 / -1; display:grid; gap:8px; margin-top:4px; padding-top:12px; border-top:1px dashed var(--line); }

/* ---- Arrange resources editor (drag to reorder / move between / archive) - */
.bld-arr-groups { display:grid; gap:22px; }
.bld-arr-group { display:grid; gap:10px; }
.bld-arr-head { display:flex; align-items:baseline; justify-content:space-between; gap:10px; }
.bld-arr-list { display:grid; gap:8px; min-height:48px; padding:6px; border:1px dashed var(--line); border-radius:12px; transition:border-color .15s, background .15s; }
.bld-arr-list.over { border-color:var(--accent); border-style:solid; background:var(--accent-soft); }
.bld-arr-empty { margin:0; padding:11px 8px; font-size:.82rem; color:var(--faint); text-align:center; }
.bld-arr-item { display:grid; grid-template-columns:22px 42px 1fr; align-items:center; gap:12px; padding:9px 11px; border:1px solid var(--line); border-radius:10px; background:var(--surface); cursor:grab; }
.bld-arr-item:active { cursor:grabbing; }
.bld-arr-item.dragging { opacity:.55; border-color:var(--accent); box-shadow:0 8px 22px -10px rgba(0,0,0,.35); }
.bld-arr-thumb { width:42px; height:26px; border-radius:5px; overflow:hidden; background:var(--hair); display:block; }
.bld-arr-thumb img { width:100%; height:100%; object-fit:cover; display:block; }
.bld-arr-text { display:flex; align-items:center; justify-content:space-between; gap:10px; min-width:0; }
.bld-arr-title { font-weight:600; font-size:.92rem; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.bld-arr-text .bld-badge { flex:0 0 auto; font-size:.64rem; padding:4px 9px; }

/* Archived items: a divider, then a muted drop zone you can drag back out of. */
.bld-arr-divider { border:0; border-top:1px solid var(--line); margin:26px 0 4px; }
.bld-arr-archived .bld-section-title { color:var(--soft); }
.bld-arr-archived .bld-arr-list { background:color-mix(in srgb, var(--hair) 60%, transparent); }
.bld-arr-archived .bld-arr-item { opacity:.72; }
.bld-arr-archived .bld-arr-item:hover { opacity:1; }
.bld-arr-archived .bld-hint { margin:-2px 0 10px; }
.bld-cat-move-row { display:flex; flex-wrap:wrap; gap:8px; align-items:center; }
.bld-cat-move-row .bld-select { flex:1; min-width:140px; }

/* ---- Danger zone: archive an existing resource --------------------------- */
.bld-danger { border-top:1px solid var(--hair); margin-top:8px; padding-top:18px; }
.bld-danger .bld-section-title { color:color-mix(in srgb, #c0392b 70%, var(--ink)); }
html[data-theme="dark"] .bld-danger .bld-section-title { color:#e8897f; }
.bld-danger-slot { margin-top:12px; }
.bld-archive-btn { appearance:none; cursor:pointer; font-family:var(--f-sans); font-weight:600; font-size:.86rem; padding:10px 16px; border-radius:9px; background:transparent; color:#c0392b; border:1.5px solid color-mix(in srgb,#c0392b 45%,var(--line)); }
.bld-archive-btn:hover { background:color-mix(in srgb,#c0392b 10%,transparent); border-color:#c0392b; }
.bld-archive-btn.is-confirm { background:#c0392b; color:#fff; border-color:#c0392b; }
.bld-archive-btn.is-confirm:hover { background:#a93226; }
.bld-danger-q { margin:0 0 10px; font-size:.9rem; color:var(--ink-2); font-weight:600; }
.bld-danger-actions { display:flex; gap:10px; }
/* ---- Delete: same danger-zone treatment, but the button is solid by default
   (not just on confirm) to read as more severe/final than Archive. ---------- */
.bld-danger-delete { border-top:1px dashed color-mix(in srgb,#c0392b 35%,var(--hair)); margin-top:18px; padding-top:18px; }
.bld-delete-btn { background:color-mix(in srgb,#c0392b 8%,transparent); }
.bld-delete-btn:hover { background:color-mix(in srgb,#c0392b 16%,transparent); }
.bld-archive-cancel { appearance:none; cursor:pointer; font-family:var(--f-sans); font-weight:600; font-size:.86rem; padding:10px 16px; border-radius:9px; background:transparent; color:var(--soft); border:1.5px solid var(--line); }
.bld-archive-cancel:hover { color:var(--ink); border-color:var(--ink-2); }

/* ---- Site colors editor -------------------------------------------------- */
.bld-theme-seg button { padding:5px 13px; }
.bld-sc-reset { margin-top:4px; }

/* ---- Visual Style: labeled color/font rows bound to a site role ---------- */
.bld-vs-list { display:grid; gap:10px; }
/* 8px gap between the color/font list and its "Add" button. */
.bld-vs-add { margin-top:8px; }
.bld-vs-preview { padding:16px; margin-bottom:14px; background:var(--bg); border:1px dashed var(--line); border-radius:12px; }
.bld-vs-preview .bld-empty { margin:0; }
.bld-vs-row { display:grid; grid-template-columns:1fr auto; grid-template-rows:auto auto; gap:8px 12px; align-items:center; background:var(--bg); border:1px solid var(--line); border-radius:12px; padding:12px; }
.bld-vs-row-main { grid-column:1; grid-row:1; display:flex; gap:8px; align-items:center; position:relative; }
.bld-vs-row-main .bld-vs-label { flex:1 1 auto; min-width:0; }
.bld-vs-row-main .bld-vs-role { flex:0 0 150px; width:150px; min-width:0; text-overflow:ellipsis; overflow:hidden; }
/* Custom label-picker popover (replaces native <datalist>, which filters its
   own suggestions to the input's current text — useless once a label is
   filled in). Anchored to .bld-vs-row-main via that element's position:relative. */
.bld-label-menu { position:absolute; top:calc(100% + 4px); left:0; right:0; z-index:20; max-height:220px; overflow-y:auto; background:var(--surface); border:1px solid var(--line); border-radius:10px; box-shadow:0 14px 34px rgba(22,22,31,0.18); padding:6px; display:grid; gap:2px; }
.bld-label-menu-row { display:flex; align-items:center; gap:4px; }
.bld-label-menu-pick { flex:1; text-align:start; appearance:none; cursor:pointer; background:none; border:0; border-radius:7px; padding:8px 10px; font-family:var(--f-sans); font-size:.86rem; color:var(--ink); }
.bld-label-menu-pick:hover { background:var(--bg); color:var(--accent-text); }
.bld-label-menu-del { flex:none; appearance:none; cursor:pointer; width:26px; height:26px; border-radius:7px; border:0; background:none; color:var(--faint); font-size:1.05rem; line-height:1; }
.bld-label-menu-del:hover { color:var(--warn); background:var(--bg); }
.bld-vs-row > .bld-color-row { grid-column:1; grid-row:2; }
/* Contrast checker badge: color is never the only signal — an icon (check/
   cross) and the numeric ratio are always shown too, for colorblind users. */
.bld-contrast-badge { flex:0 0 auto; display:flex; align-items:center; gap:4px; padding:4px 9px; border-radius:999px; font-size:.72rem; font-weight:700; font-family:var(--f-mono); white-space:nowrap; }
.bld-contrast-badge.is-pass { color:var(--ok); background:color-mix(in srgb, var(--ok) 16%, transparent); }
.bld-contrast-badge.is-fail { color:var(--warn); background:color-mix(in srgb, var(--warn) 16%, transparent); }
.bld-contrast-icon { font-size:.9rem; line-height:1; }
.bld-vs-row > .bld-icon-btn { grid-column:2; grid-row:1 / span 2; align-self:center; }
.bld-vs-row > .bld-vs-actions { grid-column:2; grid-row:1 / span 2; align-self:center; display:flex; align-items:center; gap:6px; }
.bld-vs-move { display:flex; flex-direction:column; gap:4px; }

/* Carousel running order. Same row chrome as the Arrange screen, plus a
   position number and a filename, and narrower arrows since the rows are
   short. */
.bld-carousel-order .frp-group:first-child { margin-top:2px; }
.bld-co-list { display:flex; flex-direction:column; gap:6px; margin-bottom:6px; }
.bld-co-item { grid-template-columns:22px 20px 42px 1fr auto; }
.bld-co-num { font-family:var(--f-mono); font-size:.72rem; color:var(--faint); text-align:center; }
.bld-co-name { font-family:var(--f-mono); font-size:.74rem; color:var(--soft); overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.bld-co-item .bld-vs-move { flex-direction:row; gap:3px; }
/* Upload button for one carousel. Sits under that carousel's list rather than
   under both, because the two write to differently-named files and a single
   shared button could not know which you meant. */
.bld-co-upload { margin:2px 0 4px; }
.bld-vs-move .bld-icon-btn { width:26px; height:16px; font-size:.7rem; border-radius:5px; }
.bld-vs-font-row { grid-template-columns:1fr; }
.bld-vs-font-main { display:flex; gap:8px; align-items:center; }
.bld-vs-font-main .bld-vs-font-name { flex:1; }
.bld-font-preview { font-size:1.5rem; line-height:1.25; padding-top:10px; margin-top:2px; border-top:1px dashed var(--line); color:var(--ink); min-height:1.6em; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }

/* ---- Per-font display options (small caps / italic / case / weight / tracking) ---- */
.bld-vs-font-opts { grid-column:1 / -1; display:flex; flex-wrap:wrap; align-items:center; gap:8px 12px; margin-top:10px; padding-top:10px; border-top:1px dashed var(--line); }
.bld-vs-opt { display:flex; align-items:center; gap:6px; font-size:.72rem; font-weight:600; color:var(--soft); white-space:nowrap; }
.bld-vs-opt input[type="checkbox"] { width:15px; height:15px; accent-color:var(--accent); cursor:pointer; }
.bld-vs-opt-sel { width:auto; padding:5px 8px; font-size:.8rem; }
.bld-vs-opt-num { width:62px; padding:5px 8px; font-size:.8rem; }
/* Row header balance: the general Group label is narrow (it doesn't need much),
   the specific Tag field is wide (~half) so custom tags are easy to type. */
.bld-vs-font-row .bld-vs-row-main .bld-vs-label { flex:0 1 38%; }
.bld-vs-tag { flex:1 1 auto; min-width:0; }
.bld-range-row { display:flex; align-items:center; gap:12px; }
.bld-range { flex:1; accent-color:var(--accent); }

/* ---- Site look: full-width mockup cards, one per skin (Page Visual Style
   screen). Each card's mock background/headline/dots are set inline per
   skin from SKIN_TOKENS in builder.js — only the chrome (border, selection
   state, label strip) is styled here. ---- */
.bld-skin-list { display:grid; gap:14px; }
.bld-skin-card { display:block; width:100%; padding:0; appearance:none; cursor:pointer; text-align:start; background:var(--surface); border:2px solid var(--line); border-radius:14px; overflow:hidden; transition:border-color .15s, box-shadow .15s; }
.bld-skin-card:hover { border-color:color-mix(in srgb, var(--accent) 45%, var(--line)); }
.bld-skin-card.is-selected { border-color:var(--accent); box-shadow:0 0 0 3px color-mix(in srgb, var(--accent) 22%, transparent); }
.bld-skin-mock { position:relative; padding:26px 24px; display:flex; flex-direction:column; gap:16px; }
.bld-skin-mock-headline { font-size:1.35rem; line-height:1.3; font-weight:600; }
.bld-skin-mock-dots { display:flex; gap:8px; }
.bld-skin-dot { width:16px; height:16px; border-radius:50%; border:1px solid; opacity:.85; }
.bld-skin-check { position:absolute; top:14px; inset-inline-end:14px; width:24px; height:24px; border-radius:50%; background:var(--accent); opacity:0; transform:scale(.6); transition:opacity .15s, transform .15s; }
.bld-skin-check::after { content:""; position:absolute; inset:0; margin:auto; width:6px; height:10px; border-inline-end:2px solid #fff; border-block-end:2px solid #fff; transform:rotate(45deg) translate(-1px,-2px); }
.bld-skin-card.is-selected .bld-skin-check { opacity:1; transform:scale(1); }
.bld-skin-label { display:block; padding:10px 16px; font-family:var(--f-sans); font-size:.88rem; font-weight:600; color:var(--ink); background:var(--surface); border-top:1px solid var(--line); }
.bld-range-out { font-family:var(--f-mono); font-size:.8rem; color:var(--soft); min-width:52px; text-align:end; flex:none; }

@media (max-width:520px) {
  .bld-cat-names { grid-template-columns:1fr; }
}

/* ---------------------------------------------------------------------------
   404 / not found  (404.php + unknown resource slugs)
   --------------------------------------------------------------------------- */
.notfound { padding:90px 0 100px; }
.notfound .wrap { display:grid; grid-template-columns:300px 1fr; gap:64px; align-items:center; }
.nf-mark { position:relative; aspect-ratio:var(--ar-square); border-radius:20px; border:1px solid var(--line); background:var(--accent-soft); display:grid; place-items:center; overflow:hidden; }
/* Decorative diagonal grid — drawn with a pseudo-element (no empty markup span). */
.nf-mark::before { content:""; position:absolute; inset:0; background-image:repeating-linear-gradient(135deg, transparent 0 15px, color-mix(in srgb,var(--accent) 7%,transparent) 15px 16px); }
.nf-mark .nf-big { position:relative; font-family:var(--f-display); font-weight:700; font-size:clamp(4.2rem,9vw,6rem); letter-spacing:-0.04em; color:var(--accent-text); line-height:1; }
.nf-text .eyebrow { margin-bottom:16px; font-family:var(--f-mono); }
.nf-text h1 { font-size:clamp(2.2rem,5vw,3.4rem); font-weight:600; letter-spacing:-0.03em; line-height:1.02; }
.nf-text p { margin:22px 0 0; font-size:1.12rem; color:var(--ink-2); max-width:46ch; }
.nf-actions { display:flex; gap:12px; margin-top:32px; flex-wrap:wrap; }
.nf-browse { display:inline-block; margin-top:24px; font-size:0.92rem; font-weight:600; color:var(--accent-text); border-bottom:1px solid transparent; padding-bottom:2px; transition:border-color .15s; }
.nf-browse:hover { border-color:var(--accent); }

@media (max-width:760px) {
  /* Mobile: put a field's hint directly under its LABEL rather than under the
     control. On a phone the on-screen keyboard covers everything below the
     input you just tapped, which is exactly where the guidance used to sit —
     so the tip was invisible at the moment you needed it. Desktop keeps the
     hint under the control, where it reads as a footnote. */
  .bld-field { display:flex; flex-direction:column; }
  .bld-field > .bld-label { order:0; }
  .bld-field > .bld-hint  { order:1; }
  .bld-field > :not(.bld-label):not(.bld-hint) { order:2; }

  .notfound { padding:56px 0 72px; }
  .notfound .wrap { grid-template-columns:1fr; gap:36px; }
  .nf-mark { width:160px; aspect-ratio:var(--ar-square); border-radius:16px; }
}

/* ===========================================================================
   RESOURCE DETAIL — hero, reviewer callout, findings grid
   =========================================================================== */

/* Hero: title + summary on the left, screenshot on the right. */
.detail-hero { display:grid; grid-template-columns:1fr minmax(0,46%); gap:46px; align-items:center; }
.detail-hero-copy { order:1; }
.detail-hero-media { order:2; }
.detail-hero .plate { margin-top:0; }
/* The thumbnail links to the work, captioned with what the work IS. The
   caption sits UNDER the image rather than over it — an overlay would cover
   the slide content that makes the thumbnail worth showing. */
.detail-hero .plate-link { display:block; text-decoration:none; color:inherit; }
.detail-hero .plate-link .plate { display:grid; transition:border-color .16s; }
.detail-hero .plate-link:hover .plate { border-color:var(--accent); }
.plate-cap { display:block; margin-top:10px; }
.plate-cap-main { display:block; font-size:0.9rem; font-weight:650; color:var(--accent-text); }
.plate-cap-go { margin-inline-start:6px; transition:transform .16s; display:inline-block; }
.plate-link:hover .plate-cap-go { transform:translateX(3px); }
.plate-cap-meta { display:block; margin-top:2px; font-size:0.8rem; color:var(--muted); }
.detail-hero-copy h1 { max-width:16ch; }
.detail-hero-copy .summary { margin-top:20px; max-width:52ch; }

/* On-brand "for reviewers" callout, pinned under the spec bar. Collapsible
   (<details>) and collapsed by default — supporting context, not the headline,
   so it stays out of the way until a reviewer opens it. */
.reviewer-callout { margin-top:22px; background:var(--accent-soft); border:1px solid color-mix(in srgb,var(--accent) 24%,var(--line)); border-inline-start:3px solid var(--accent); border-radius:var(--radius); padding:0; overflow:hidden; }
.reviewer-callout .rc-label { list-style:none; cursor:pointer; display:flex; align-items:center; justify-content:space-between; gap:12px; padding:16px 22px; font-family:var(--f-mono); font-size:0.68rem; font-weight:700; letter-spacing:0.14em; text-transform:uppercase; color:var(--accent-ink); user-select:none; }
.reviewer-callout .rc-label::-webkit-details-marker { display:none; }
.reviewer-callout .rc-chevron { flex:none; width:9px; height:9px; border-right:2px solid var(--accent-ink); border-bottom:2px solid var(--accent-ink); transform:rotate(45deg) translateY(-2px); transition:transform .22s ease; }
.reviewer-callout[open] .rc-chevron { transform:rotate(-135deg) translateY(1px); }
.reviewer-callout ul.clean { gap:9px; padding:0 22px 18px; }
.reviewer-callout ul.clean li { font-size:0.98rem; color:var(--ink-2); }
.reviewer-callout[open] .rc-label { padding-bottom:10px; }

/* Findings: a full-width card grid inside a narrative section. */
.detail-section--wide .section-body { max-width:none; }

/* ---------------------------------------------------------------------------
   Implement / Evaluate — one record at a time
   --------------------------------------------------------------------------- */
/* A NUMBERED RECORD heading ("Implementation #1") against a phase section
   heading ("Evaluation"). It is a smaller order of thing: one of several
   rollouts, not one of the five phases. Same treatment the editor gives the
   same string, so the two screens name it identically. */
.detail-section .section-head h2.rec-name { font-family:var(--f-sans); font-size:.82rem;
  font-weight:700; letter-spacing:.12em; text-transform:uppercase; color:var(--accent-text); }
.rec-when { display:block; margin-top:7px; font-size:.9rem; color:var(--soft); }
.rec-switch { display:block; width:100%; margin-top:10px; font-family:var(--f-sans); font-size:.86rem;
  font-weight:600; color:var(--ink); background:var(--surface); border:1px solid var(--line);
  border-radius:9px; padding:7px 30px 7px 11px; cursor:pointer; appearance:none;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%2362636F' stroke-width='3' stroke-linecap='round'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E");
  background-repeat:no-repeat; background-position:right 10px center; }
[dir="rtl"] .rec-switch { background-position:left 10px center; padding:7px 11px 7px 30px; }
.rec-switch:focus-visible { outline:none; border-color:var(--accent); box-shadow:0 0 0 3px var(--accent-soft); }
.rec-nav { display:flex; gap:6px; margin-top:9px; }
.rec-nav button { flex:1; appearance:none; cursor:pointer; font-family:var(--f-sans); font-size:.8rem;
  font-weight:600; color:var(--soft); background:var(--surface); border:1px solid var(--line);
  border-radius:8px; padding:6px 8px; transition:color .15s, border-color .15s; }
.rec-nav button:hover:not(:disabled) { color:var(--accent-text); border-color:var(--accent); }
.rec-nav button:disabled { opacity:.4; cursor:default; }
.rec-count { font-size:.74rem; color:var(--faint); margin:8px 0 0; }
/* Only ever hides where scripting can un-hide. Without .has-js every record
   stays on the page, stacked — which is what a crawler and a no-JS reader get. */
body.has-js .rec-body[hidden] { display:none; }

/* The facts of one rollout. Label over value, the same treatment the spec bar
   uses at the top of the page, so the two read as the same kind of thing. */
.impl-facts { display:grid; grid-template-columns:repeat(auto-fit,minmax(160px,1fr)); gap:18px 26px; margin:0 0 22px; }
.impl-fact dt { font-size:.66rem; font-weight:600; letter-spacing:.14em; text-transform:uppercase; color:var(--label-ink); margin-bottom:5px; }
.impl-fact dd { margin:0; font-size:1rem; color:var(--ink); }
/* What actually went out. Small, because it is provenance rather than content. */
.impl-versions { display:flex; flex-wrap:wrap; gap:6px 10px; margin:0 0 22px; padding:11px 14px;
  background:var(--surface); border:1px solid var(--line); border-radius:11px; font-size:.86rem; color:var(--soft); }
.impl-versions .iv-label { width:100%; font-size:.66rem; font-weight:600; letter-spacing:.14em; text-transform:uppercase; color:var(--label-ink); }
.impl-versions .iv-item { color:var(--ink-2); }
.impl-versions .iv-v { font-family:var(--f-mono); font-size:.78rem; font-weight:700; color:var(--accent-text); }
.impl-versions .iv-sep { color:var(--faint); }

/* A sub-heading inside a record, quieter than the section's own h2. */
.sub-head { font-family:var(--f-sans); font-size:.72rem; font-weight:700; letter-spacing:.14em;
  text-transform:uppercase; color:var(--label-ink); margin:30px 0 12px; }
.section-body > .sub-head:first-child { margin-top:0; }
.plain-list { margin:0 0 8px; padding-inline-start:1.25em; }
.plain-list li { margin-bottom:8px; }
.plain-list li:last-child { margin-bottom:0; }

/* Issues by priority. The priority is NAMED in the first cell, so colour is a
   second channel on a labelled row and never the only carrier. Ink is pinned
   per theme — these tints stop being backgrounds --ink can sit on. */
.sb-table tr.sev td { background:var(--sev-bg); color:var(--sev-ink); }
.sb-table tr.sev td:first-child { font-weight:700; }
.sb-table tr.sev-critical { --sev-bg:#FDE7E4; --sev-ink:#16161F; }
.sb-table tr.sev-major    { --sev-bg:#FDF3D6; --sev-ink:#16161F; }
.sb-table tr.sev-minor    { --sev-bg:#E6F0FC; --sev-ink:#16161F; }
.sb-table tr.sev-normal   { --sev-bg:transparent; --sev-ink:var(--ink); }
html[data-theme="dark"] .sb-table tr.sev-critical { --sev-bg:#4A2320; --sev-ink:#F4E9E7; }
html[data-theme="dark"] .sb-table tr.sev-major    { --sev-bg:#46391A; --sev-ink:#F5EFE2; }
html[data-theme="dark"] .sb-table tr.sev-minor    { --sev-bg:#1E3350; --sev-ink:#E5EDF7; }

/* Results. Stat tiles, not a chart: a handful of headline numbers with no time
   axis. Proportional figures, not tabular — tabular-nums gives every digit the
   width of a 0, which reads loose at this size and nothing here aligns down a
   column. */
.stat-row { display:grid; grid-template-columns:repeat(auto-fit,minmax(150px,1fr)); gap:12px; margin:0 0 8px; }
.stat { padding:16px 18px; background:var(--surface); border:1px solid var(--line); border-radius:12px; }
.stat-label { font-size:.8rem; color:var(--soft); margin-bottom:6px; }
.stat-value { font-family:var(--f-sans); font-size:2rem; font-weight:600; line-height:1.1; color:var(--ink); letter-spacing:-0.02em; }

/* A quote is somebody's voice, so it gets a rule and italics rather than a
   card — cards read as UI, and this is testimony. */
.quotes { display:grid; gap:16px; margin:0 0 8px; }
.quote { margin:0; padding:2px 0 2px 18px; border-inline-start:3px solid var(--accent-soft); }
.quote p { margin:0; font-size:1.06rem; font-style:italic; color:var(--ink-2); }
.quote-src { font-size:.72rem; font-weight:600; letter-spacing:.14em; text-transform:uppercase; color:var(--label-ink); margin:20px 0 9px; }

/* Whether the objectives were met. The WORD carries the state; the colour and
   the dot are a second channel, never the only one. */
.met { display:inline-flex; align-items:center; gap:9px; padding:9px 15px; border-radius:999px;
  font-size:.9rem; font-weight:700; margin:0 0 14px; }
.met-dot { width:9px; height:9px; border-radius:50%; background:currentColor; flex:none; }
.met-yes  { color:var(--ok);   background:color-mix(in srgb, var(--ok) 14%, transparent); }
.met-part { color:var(--warn); background:color-mix(in srgb, var(--warn) 14%, transparent); }
.met-no   { color:#C0392B;     background:color-mix(in srgb, #C0392B 14%, transparent); }
html[data-theme="dark"] .met-no { color:#F0857A; }
.findings { display:flex; flex-direction:column; gap:22px; }
.finding-row { display:flex; gap:22px; justify-content:center; flex-wrap:wrap; }
.finding-card { flex:1 1 300px; min-width:0; max-width:560px; display:flex; flex-direction:column; background:var(--surface); border:1px solid var(--line); border-radius:14px; overflow:hidden; box-shadow:0 1px 3px rgba(22,22,31,0.04); }
.finding-band { background:var(--fb,var(--accent)); color:var(--fb-ink,#fff); font-family:var(--f-display); font-weight:700; font-size:1.05rem; letter-spacing:-0.01em; padding:12px 20px; }
.finding-claim { flex:1; padding:20px; font-size:1.1rem; line-height:1.4; font-weight:500; color:var(--ink); }
.finding-claim strong { font-weight:700; }
.finding-evidence { background:color-mix(in srgb,var(--fb,var(--accent)) 12%,var(--surface)); border-top:1px solid var(--line); padding:16px 20px; }
.finding-evidence ul { list-style:none; margin:0; padding:0; display:grid; gap:10px; }
.finding-evidence li { position:relative; padding-inline-start:18px; font-size:0.9rem; line-height:1.45; color:var(--ink-2); }
.finding-evidence li::before { content:""; position:absolute; inset-inline-start:2px; top:0.6em; width:6px; height:6px; border-radius:50%; background:var(--fb,var(--accent)); }

/* Collapsible on small screens (see phpsite.js). On desktop it's forced open
   and the toggle is hidden; on mobile it starts collapsed and the toggle shows. */
.findings-collapse { display:block; }
.findings-collapse > summary { list-style:none; cursor:pointer; }
.findings-collapse > summary::-webkit-details-marker { display:none; }
.findings-toggle { display:none; align-items:center; gap:10px; width:100%; padding:13px 16px; background:var(--surface); border:1px solid var(--line); border-radius:12px; font-family:var(--f-sans); font-weight:600; font-size:0.98rem; color:var(--ink); }
.findings-toggle .ft-count { display:inline-grid; place-items:center; min-width:22px; height:22px; padding:0 6px; border-radius:11px; background:var(--accent-soft); color:var(--accent-ink); font-size:0.78rem; font-weight:700; }
.findings-toggle .ft-chevron { margin-inline-start:auto; width:9px; height:9px; border-right:2px solid var(--soft); border-bottom:2px solid var(--soft); transform:rotate(45deg); transition:transform .2s ease; }
.findings-collapse[open] .findings-toggle .ft-chevron { transform:rotate(-135deg); }
.findings-collapse[open] .findings-toggle { margin-bottom:22px; }

@media (max-width:860px) {
  .detail-hero { grid-template-columns:1fr; gap:26px; }
  /* Image BELOW the title and description on a phone. It used to be order:-1,
     which put a 16:9 picture above the words — so the first screenful was a
     thumbnail and the reader had to scroll to learn what they were looking at.
     On a single column the title has to come first; the image is now the
     payoff at the end of the hero rather than a gate in front of it. */
  .detail-hero-media { order:2; }
  .finding-card { max-width:none; }
}

/* ---- Builder: findings editor (owner Settings panel) ---- */
.bld-finding-card { border:1px solid var(--line); border-radius:12px; padding:14px 16px; margin-bottom:12px; background:var(--bg); }
.bld-finding-head { display:flex; align-items:center; justify-content:space-between; margin-bottom:6px; }
.bld-finding-num { font-family:var(--f-display); font-weight:700; font-size:0.9rem; color:var(--accent-ink); }
.bld-sub-label { display:block; font-size:0.68rem; font-weight:700; letter-spacing:0.08em; text-transform:uppercase; color:var(--soft); margin:12px 0 6px; }
.bld-add-sm { font-size:0.8rem; padding:6px 11px; margin-top:8px; }

/* Parts editor. Reuses the findings card so a repeatable row looks the same
   wherever it appears in the builder; only the header tools and the two
   side-by-side selects are new. */
.bld-part-tools { display:flex; align-items:center; gap:8px; }
.bld-part-lead { font-family:var(--f-mono); font-size:.6rem; letter-spacing:.1em; text-transform:uppercase;
  color:var(--accent-text); background:var(--accent-soft); border-radius:5px; padding:3px 7px; margin-inline-start:10px; }
.bld-part-pair { display:grid; grid-template-columns:1fr 1fr; gap:12px; }
@media (max-width:560px){ .bld-part-pair { grid-template-columns:1fr; gap:0; } }

/* ===========================================================================
   RIGHT-TO-LEFT LANGUAGES (Hebrew, and any future [dir="rtl"] locale)
   ---------------------------------------------------------------------------
   Most of the site's layout already mirrors correctly for free: flexbox/grid
   follow the inline direction, and .wrap/most spacing already uses logical
   properties (margin-inline, padding-inline) or was converted to them above
   (border-inline-*, inset-inline-*, text-align:start, etc.) specifically so
   this block could stay small. What's left here is only what CAN'T be
   expressed as a logical property: transforms (which don't have a
   direction-aware equivalent) and static "→"/"←" glyphs baked into markup,
   which are visual arrows, not simply positioned content.
   =========================================================================== */
[dir="rtl"] .addie-nav a::after { transform-origin:right; }
[dir="rtl"] .proj-row:not(.placeholder):hover .proj-arrow .ar { transform:scaleX(-1) translateX(6px); }
@media (prefers-reduced-motion: reduce) {
  [dir="rtl"] .proj-row:not(.placeholder):hover .proj-arrow .ar { transform:scaleX(-1) translateX(4px); }
}
/* "←" in the back-links and "→" on project-card arrows (.ar) are directional
   glyphs, not decoration — scaleX(-1) flips the character itself so "back"
   still visually points toward where you came from and "view resource"
   still points toward where the link goes, in whichever direction that is. */
[dir="rtl"] .back-arrow, [dir="rtl"] .proj-arrow .ar { display:inline-block; transform:scaleX(-1); }
/* The persistent hero link, the full-resource cover, the hero caption and the
   parts rows all carry a directional glyph too — "↗" for "opens away from
   here" and "→" for "this way". Same treatment and same reason as the
   back-links above: flip the CHARACTER, so "away" still reads as away when the
   page runs right-to-left. Missing these left every new arrow on the resource
   page pointing back into the text in Hebrew.

   The ::after arrows sit inside a flipped box, so transform-origin doesn't
   matter; the inline ones need display:inline-block for the transform to
   apply at all. */
[dir="rtl"] .addie-nav a.addie-nav-open .ano-label::after,
[dir="rtl"] .fr-follow .frf-label::after,
[dir="rtl"] .fr-cover.is-external .frc-cap-main::after { display:inline-block; transform:scaleX(-1); }
[dir="rtl"] .plate-cap-go,
[dir="rtl"] .frp-go { display:inline-block; transform:scaleX(-1); }
/* The hover nudge travels with the reader, so it has to reverse as well —
   translateX is physical and would otherwise push the arrow backwards. */
[dir="rtl"] .plate-link:hover .plate-cap-go { transform:scaleX(-1) translateX(3px); }

/* Carousel prev/next (media.js) reuse the same ‹ / › glyphs for both
   directions — inset-inline-start/end above already swapped which SIDE each
   button sits on; this flips the glyph so it still points the right way. */
[dir="rtl"] .carousel-arrow { transform:translateY(-50%) scaleX(-1); }

/* ---- Publishing recipe under the resource-type picker ---- */
.bld-recipe { margin-top:12px; border-left:3px solid var(--accent-soft); padding:2px 0 2px 14px; }
.bld-recipe-head { font-family:var(--f-mono); font-size:.66rem; letter-spacing:.14em; text-transform:uppercase; color:var(--faint); margin-bottom:8px; }
.bld-recipe ol { margin:0; padding-left:18px; }
.bld-recipe li { font-size:.86rem; line-height:1.55; color:var(--soft); margin-bottom:7px; }
.bld-recipe-warn { font-size:.84rem; line-height:1.55; color:var(--warn); margin:10px 0 0; font-weight:500; }
.bld-check { display:flex; align-items:flex-start; gap:10px; cursor:pointer; }
.bld-check input { margin-top:3px; accent-color:var(--accent); width:16px; height:16px; flex:none; }
.bld-check span { font-size:.9rem; font-weight:600; }

/* ===== The persistent hero link =========================================
   Two presentations of one destination. WHICH one is decided by measurement at
   runtime, not by a width guess — scripts/phpsite.js puts `fr-bar-fits` on
   <html> when the ADDIE bar genuinely has room for the item, and takes it off
   when it doesn't.

   A fixed breakpoint was wrong here and looked it. The bar's spare room depends
   on how many ADDIE phases this particular resource has (three links or six),
   on the skin (Bold docks its nav into a fixed sidebar and loses ~145px of
   content width; the others don't), and on the rendered width of the label in
   whatever language is active. One number cannot express that, so a number
   tuned for the worst case sent every other case to the pill with half the bar
   still empty. */
.addie-nav a.addie-nav-open { display:none; }
:root.fr-bar-fits .addie-nav a.addie-nav-open {
  display:flex; align-items:center; gap:10px; margin-inline-start:auto;
  flex:none; padding:6px 12px 6px 8px; border:1.5px solid var(--line); border-radius:999px;
  text-decoration:none; color:var(--soft); font-weight:600; font-size:.86rem; white-space:nowrap;
  transition:color .16s, border-color .16s, background .16s;
}
:root.fr-bar-fits .addie-nav a.addie-nav-open:hover { color:var(--on-accent); background:var(--accent); border-color:var(--accent); }
.addie-nav a.addie-nav-open .ano-thumb { flex:none; width:28px; height:18px; border-radius:4px; overflow:hidden; background:var(--hair); display:block; }
.addie-nav a.addie-nav-open .ano-thumb img { width:100%; height:100%; object-fit:cover; display:block; }
.addie-nav a.addie-nav-open .ano-label::after { content:" \2197"; }
/* The phase links yield first as the bar narrows — they already scroll. */
.addie-nav ul { min-width:0; }

/* The pill, for every case where the bar item does not fit. Hidden until the
   hero has scrolled out of view (see syncFollow in scripts/phpsite.js), and it
   stands down near the footer so it never covers those links. */
.fr-follow { position:fixed; inset-block-end:20px; inset-inline-end:20px; z-index:70;
  display:flex; align-items:center; gap:10px; padding:8px 14px 8px 10px;
  border:1.5px solid var(--line); border-radius:999px; background:var(--surface);
  box-shadow:0 10px 30px -12px rgba(0,0,0,.4); text-decoration:none;
  color:var(--ink); font-weight:600; font-size:.88rem; white-space:nowrap;
  opacity:0; transform:translateY(8px); pointer-events:none;
  transition:opacity .22s, transform .22s, border-color .16s; }
.fr-follow.is-on { opacity:1; transform:none; pointer-events:auto; }
.fr-follow:hover { border-color:var(--accent); }
.fr-follow .frf-thumb { flex:none; width:34px; height:22px; border-radius:5px; overflow:hidden;
  background:var(--hair); display:block; }
.fr-follow .frf-thumb img { width:100%; height:100%; object-fit:cover; display:block; }
.fr-follow .frf-label::after { content:" \2197"; }
:root.fr-bar-fits .fr-follow { display:none; }
@media (prefers-reduced-motion:reduce) { .fr-follow { transition:opacity .01s; transform:none; } }

/* ===== The kit, in the header ============================================
   Only the parts list lives up here now; the embed went back to the end of
   Develop (see .fr-cover below). */
.fr-lead { margin:18px 22px 0; }

/* ===== The full resource, closing Develop ================================
   One cover image, two behaviours. Embeddable: a <button> that swaps itself
   for the iframe. Not embeddable: an <a> to a new tab. Identical to look at,
   because the reader should not have to care which one they got — and the
   choice was measured on the server, not guessed here. */
.fr-cover { display:block; width:100%; padding:0; border:0; background:none;
  font:inherit; color:inherit; text-align:start; cursor:pointer; text-decoration:none; }
.fr-cover .frc-plate { position:relative; display:block; aspect-ratio:var(--ar-video);
  border:1px solid var(--line); border-radius:18px; overflow:hidden; background:var(--accent-soft);
  background-image:repeating-linear-gradient(135deg, transparent 0 18px, color-mix(in srgb,var(--accent) 6%,transparent) 18px 19px);
  display:grid; place-items:center; transition:border-color .16s; }
.fr-cover .frc-plate img { width:100%; height:100%; object-fit:cover; display:block; }
.fr-cover:hover .frc-plate, .fr-cover:focus-visible .frc-plate { border-color:var(--accent); }
.fr-cover:focus-visible { outline:2px solid var(--accent); outline-offset:4px; border-radius:18px; }
/* The affordance: a soft disc with a triangle for "open this". Sits over the
   image, centred, and grows very slightly on hover. */
.frc-badge { position:absolute; inset:50% auto auto 50%; translate:-50% -50%;
  width:64px; height:64px; border-radius:50%; background:color-mix(in srgb, var(--surface) 88%, transparent);
  border:1.5px solid var(--line); backdrop-filter:blur(6px);
  display:grid; place-items:center; transition:transform .18s, border-color .18s; }
/* Play — video only. The triangle is the loudest affordance on the page and it
   promises playback, so it may not appear on a PDF or a slide deck. */
.frc-badge--play::before { content:""; width:0; height:0; margin-inline-start:4px;
  border-block:11px solid transparent; border-inline-start:18px solid var(--accent); }
/* Opens in place: two arrows pushing apart, i.e. "expand this here". */
.frc-badge--open::before { content:""; width:20px; height:20px; background:var(--accent);
  -webkit-mask:var(--icon-expand) center / contain no-repeat; mask:var(--icon-expand) center / contain no-repeat; }
/* Leaves the site: the same corner arrow the caption already appends. */
.frc-badge--external::before { content:""; width:19px; height:19px; background:var(--accent);
  -webkit-mask:var(--icon-external) center / contain no-repeat; mask:var(--icon-external) center / contain no-repeat; }
:root {
  --icon-expand:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M15 3h6v6'/%3E%3Cpath d='M9 21H3v-6'/%3E%3Cpath d='M21 3l-7 7'/%3E%3Cpath d='M3 21l7-7'/%3E%3C/svg%3E");
  --icon-external:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M7 17L17 7'/%3E%3Cpath d='M8 7h9v9'/%3E%3C/svg%3E");
}
.fr-cover:hover .frc-badge { transform:scale(1.06); border-color:var(--accent); }
.frc-cap { display:block; margin-top:12px; }
.frc-cap-main { display:block; font-family:var(--f-display); font-weight:600; font-size:1.05rem; color:var(--accent-text); }
.fr-cover.is-external .frc-cap-main::after { content:" \2197"; }
.frc-cap-meta { display:block; margin-top:2px; font-size:.86rem; color:var(--soft); }
.fr-embed .fr-wrap[hidden] { display:none; }

/* The other artefacts, grouped by who uses them. */
.fr-parts { margin-top:18px; }
.frp-group { font-size:.66rem; font-weight:600; letter-spacing:.14em; text-transform:uppercase; color:var(--label-ink); margin:20px 0 9px; }
.frp-group:first-child { margin-top:6px; }
.frp-list { list-style:none; margin:0; padding:0; display:flex; flex-direction:column; gap:8px; }
.frp { display:flex; align-items:center; gap:14px; padding:12px 15px; background:var(--surface);
  border:1px solid var(--line); border-radius:12px; text-decoration:none; transition:border-color .16s; }
.frp:hover { border-color:var(--accent); }
.frp-kind { flex:none; width:38px; height:38px; border-radius:9px; display:grid; place-items:center;
  font-family:var(--f-mono); font-size:.58rem; font-weight:700; background:var(--accent-soft); color:var(--accent-ink); }
.frp-kind.is-deck { background:#FFEFD6; color:#8A5A12; }
.frp-kind.is-doc  { background:#DFF2E6; color:#1F6B41; }
.frp-kind.is-aid,.frp-kind.is-pdf { background:#E7E9FB; color:#3A3597; }
.frp-body { min-width:0; display:flex; flex-direction:column; }
.frp-title { font-weight:600; font-size:.95rem; color:var(--ink); }
.frp-meta { font-size:.82rem; color:var(--soft); margin-top:1px; }
.frp-go { margin-inline-start:auto; flex:none; color:var(--accent-text); font-size:1rem; }

@media (max-width:760px){
  .fr-lead { margin-inline:0; }
}
