/* ============================================================
   THE FILING ROOM — CABINET
   An alternative design system: the site as a drawer of hanging
   folders. Every section is a colour-tabbed folder that pulls open
   on click or as you scroll past it (see cabinet.js).
   Fonts (Fraunces / Space Mono / Inter) are enqueued in functions.php.
   ============================================================ */

:root {
  /* ---- Palette hookup: ROLES, not materials ----
     Base colours come from the theme.json palette via the
     --wp--preset--color--* properties WordPress emits into :root, so palette
     edits in the Site Editor (Styles -> Colours -> Edit palette) restyle the
     whole design. Hex fallbacks mirror theme.json and only apply where global
     styles aren't loaded.

     The palette is split so that no slug is ever both a background and a
     foreground:

       surface-*  are painted as `background`, never as text
       text-*     are painted as `color`/`fill`, never as a background
       accent-*   are backgrounds; the text on them is --on-accent-N, which
                  inc/palette.php resolves per palette by measuring contrast

     That split is the fix for the previous material-named palette (Manila,
     Paper, Ink, Rust, Brass...), where every one of those slugs was a
     background in one component and text in another — so a client choosing
     "Manila" as a panel colour also repainted the body copy with it, and no
     combination of choices could give both a readable background and readable
     text. Keep the split when adding colours: a new slug belongs to exactly
     one of the three groups, and every derived tone below is color-mix()ed
     from the group tokens, never written as a literal hex. */

  /* Backgrounds */
  --surface-page:   var(--wp--preset--color--surface-page, #f0eee9);   /* page backdrop */
  --surface-raised: var(--wp--preset--color--surface-raised, #e6e2d8); /* rail, footer, closed folder rows */
  --surface-panel:  var(--wp--preset--color--surface-panel, #d2e8ff);  /* the paper inside an open folder */
  --surface-card:   var(--wp--preset--color--surface-card, #fbf9f4);   /* file cards, review cards, inputs, photo mounts */

  /* Foregrounds */
  --text-page:     var(--wp--preset--color--text-page, #0a122a);      /* body copy on page/raised surfaces */
  --text-panel:    var(--wp--preset--color--text-panel, #861519);     /* body copy inside an open folder */
  --text-heading:  var(--wp--preset--color--text-heading, #861519);   /* headings on any surface */
  --text-on-dark:  var(--wp--preset--color--text-on-dark, #ffffff);   /* text over a dark accent */
  --text-on-light: var(--wp--preset--color--text-on-light, #861519);  /* text over a light accent */

  /* Folder accents — rotated across tabs, flags and chips. */
  --accent-1: var(--wp--preset--color--accent-1, #861519);
  --accent-2: var(--wp--preset--color--accent-2, #fae38e);
  --accent-3: var(--wp--preset--color--accent-3, #d2e8ff);
  --accent-4: var(--wp--preset--color--accent-4, #0a122a);

  /* Text on each accent. inc/palette.php overwrites these with the
     higher-contrast of --text-on-dark / --text-on-light for the accent the
     client actually chose; the values here are only the no-PHP fallback,
     matching the shipped accent defaults (1 and 4 dark, 2 and 3 light). */
  --on-accent-1: var(--text-on-dark);
  --on-accent-2: var(--text-on-light);
  --on-accent-3: var(--text-on-light);
  --on-accent-4: var(--text-on-dark);

  /* Pressed/hover states for accent fills — the accent pulled toward black. */
  --accent-1-deep: color-mix(in srgb, var(--accent-1), #000 18%);

  /* Type */
  --display: 'Fraunces', Georgia, serif;
  --mono: 'Space Mono', ui-monospace, 'SFMono-Regular', monospace;
  --body-font: 'Inter', system-ui, sans-serif;

  /* Rhythm */
  --container-max: 1180px;
  /* The nav rail carries 10 tabs plus brand and CTA — much more than the
     1180px reading-measure container has room for before the tab row is
     forced into its own horizontal scroll. The rail isn't body copy, so
     it isn't bound by that measure; give it a wider column of its own to
     use the screen space either side that --container-max leaves idle. */
  --rail-container-max: 1600px;
  --rail-h: 108px; /* tall enough for the staggered folder-tab cascade — see .tabrow below */
  --shadow-drop: 0 20px 44px rgba(0,0,0,0.18);
  --shadow-soft: 0 8px 20px rgba(0,0,0,0.12);
}

/* ---------- Surface contexts ----------
   Anything that paints its own background declares the PAIR it is painting
   with (--surface + --on-surface); everything nested inside then reads its
   muted text, hairlines and link colour from that pair instead of from a
   fixed global value. This is what makes one set of components legible on
   the cream page, the coloured folder paper and a custard form card alike.

   The derived tokens have to be restated per context rather than inherited:
   a custom property's var() references are substituted where the property is
   DECLARED, so a --text-muted declared once on :root would bake in the page
   surface and keep that value inside every panel. The grouped rule below is
   that restatement — every selector that sets a pair must also appear in it. */
:root,
.rail, .rail-menu, .foot, .stamp-cta,
.folder__tab, .folder__panel-inner,
.card, .file-card, .gr-card, .photo-clip,
.field input, .field select, .field textarea {
  --text-muted: color-mix(in srgb, var(--on-surface) 68%, var(--surface));
  --hairline: color-mix(in srgb, var(--on-surface) 20%, transparent);
  --hairline-strong: color-mix(in srgb, var(--on-surface) 38%, transparent);
  --link: var(--on-surface);
  --link-hover: color-mix(in srgb, var(--on-surface) 62%, var(--accent-1));
}

:root { --surface: var(--surface-page); --on-surface: var(--text-page); }
.rail, .rail-menu, .foot, .stamp-cta, .folder__tab { --surface: var(--surface-raised); --on-surface: var(--text-page); }
.folder:nth-of-type(odd) .folder__tab { --surface: var(--surface-page); }
.folder__panel-inner { --surface: var(--surface-panel); --on-surface: var(--text-panel); }
.file-card, .gr-card, .photo-clip,
.field input, .field select, .field textarea { --surface: var(--surface-card); --on-surface: var(--text-page); }
.card { --surface: var(--accent-2); --on-surface: var(--on-accent-2); }

/* ---------- Legacy content aliases ----------
   The pre-2026-08 material palette, kept only so that hand-written wp:html
   blocks copied out of older page content keep rendering legibly instead of
   falling back to `unset`. Each resolves to a TEXT-safe role token, because
   inline styles in content only ever used them as `color` — none of these is
   safe as a background. --cherry and --faded-document are referenced by the
   shared thefilingroom-tools enquiry-form markup, which both themes render.
   Do not use any of them in new CSS or new content. */
:root {
  --ink: var(--text-panel);
  --rust: var(--accent-1);
  --brass: var(--accent-1);
  --paper: var(--text-heading);
  --cherry: var(--accent-1);
  --faded-document: var(--hairline);
}

/* ---------- Reset ---------- */
*, *::before, *::after { box-sizing: border-box; }
/* overflow-x lives on html, not body: setting it on body forces body's
   overflow-y to compute to auto (CSS Overflow spec), which turns body
   into its own scroll container — but the page actually scrolls via
   html (document.scrollingElement), so anything inside body using
   position:sticky would anchor to a container that never itself
   scrolls and silently stop sticking. html doesn't have that problem
   since it IS the real scrolling element. */
/* overflow-anchor:none here (the actual scroll container — see the
   overflow-x comment above) is load-bearing, not decoration: as folders
   open their height grows, and the browser's scroll-anchoring feature
   compensates by nudging scrollY to keep on-screen content visually
   stable. That nudge itself fires a 'scroll' event, which the folder
   scrollspy below reads as "the user scrolled further", opening the next
   folder — growing height again, triggering another anchor-compensation
   scroll, opening the next one, and so on: a runaway feedback loop that
   doesn't stop until every folder is open. Disabling anchoring on
   .folder/.drawer (see further down) only stops the browser from picking
   *those* elements as its anchor reference — it does nothing to stop the
   scroll container from anchoring off some other element instead, which
   is exactly what was still happening. Anchoring must be killed here, on
   the container, to actually disable it. body needs the same override:
   Chromium still applied anchoring with only html set to none. */
html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; overflow-x: hidden; overflow-anchor: none; }
body {
  font-family: var(--body-font);
  background: var(--surface-page);
  color: var(--text-page);
  line-height: 1.55;
  overflow-anchor: none;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}
img { display: block; max-width: 100%; }
a { color: inherit; text-decoration: none; }
button { font: inherit; cursor: pointer; border: none; background: none; color: inherit; }
input, select, textarea { font: inherit; }
::selection { background: var(--text-page); color: var(--surface-page); }

/* ---------- WordPress default focus ring neutraliser ----------
   WP core (wp-block-library style.css) ships:
   `:where(.wp-site-blocks :focus) { outline-width: 2px; outline-style: solid; }`
   :where() gives it zero specificity, so a plain selector overrides it
   regardless of load order. Suppress it on mouse/touch click; keep a
   visible ring for keyboard users only (:focus-visible). */
.wp-site-blocks :focus { outline: none; }
.wp-site-blocks :focus-visible { outline: 2px solid var(--accent-1); outline-offset: 2px; }

/* ---------- WordPress flow-margin neutraliser ----------
   Same fix as the archival-editorial theme: WP 7.0 global styles emit
   `:root :where(.is-layout-flow) > * { margin-block: 1.2rem 0 }` at
   specificity (0,1,0). Match it with :root, scoped to this theme's
   main wrapper, above the .mt-N / .mb-N utilities so ties resolve
   in the utilities' favour. */
:root :where(.cab-main .is-layout-flow) > * + *,
:root :where(.cab-main .is-layout-constrained) > * + * { margin-block-start: 0; }

/* ---------- Scrollbar ---------- */
::-webkit-scrollbar { width: 11px; }
::-webkit-scrollbar-track { background: var(--surface-raised); }
::-webkit-scrollbar-thumb { background: var(--hairline-strong); border-radius: 6px; border: 2px solid var(--surface-raised); }
::-webkit-scrollbar-thumb:hover { background: var(--accent-1); }

/* ---------- Layout ---------- */
.container { width: 100%; max-width: var(--container-max); margin-inline: auto; padding-inline: clamp(16px, 5vw, 40px); }

/* ---------- Inline SVG icons ---------- */
.ico {
  display: inline-flex; align-items: center; justify-content: center;
  width: 1em; height: 1em; line-height: 0; flex: none;
  vertical-align: -0.14em;
}
.ico svg { width: 100%; height: 100%; display: block; fill: none; stroke: currentColor; stroke-width: 1.7; stroke-linecap: round; stroke-linejoin: round; }

/* ============================================================
   Typography
   ============================================================ */
.display {
  font-family: var(--display); font-weight: 600;
  font-size: clamp(2.35rem, 1.4rem + 4.2vw, 3.6rem);
  line-height: 1.04; letter-spacing: -0.01em;
  text-wrap: balance;
}
.h1 { font-family: var(--display); font-weight: 600; font-size: clamp(2rem, 1.3rem + 3vw, 3rem); line-height: 1.1; text-wrap: balance; }
.h2 { font-family: var(--display); font-weight: 600; font-size: clamp(1.6rem, 1.2rem + 1.6vw, 2rem); line-height: 1.2; text-wrap: balance; }
.h3 { font-family: var(--display); font-weight: 600; font-size: 1.5rem; line-height: 1.3; }
.h4 { font-family: var(--display); font-weight: 600; font-size: 1.2rem; line-height: 1.3; }
.body-lg { font-size: 1.125rem; line-height: 1.6; }
.body { font-size: 1rem; line-height: 1.6; }
.lead { font-size: clamp(1.05rem, 1rem + 0.4vw, 1.2rem); line-height: 1.65; }
.label {
  font-family: var(--mono); font-weight: 700; font-size: 0.72rem;
  line-height: 1.4; letter-spacing: 0.12em; text-transform: uppercase;
}
.caption { font-size: 0.75rem; line-height: 1.4; }
.italic { font-family: var(--display); font-style: italic; }
.text-secondary { color: var(--text-muted); }
.measure { max-width: 58ch; }
.measure-sm { max-width: 44ch; }

/* .text-secondary/.caption are used on the page chrome and inside folder
   panels alike; --text-muted is re-derived per surface context (see the
   grouped rule above), so one declaration now reads correctly on both. */
.caption { color: var(--text-muted); }

/* ============================================================
   Buttons
   ============================================================ */
.btn {
  display: inline-flex; align-items: center; gap: 0.55rem;
  font-family: var(--mono); font-weight: 700; font-size: 0.78rem;
  letter-spacing: 0.06em; text-transform: uppercase;
  padding: 0.85rem 1.4rem; border-radius: 3px;
  transition: background .2s, color .2s, border-color .2s, transform .2s, box-shadow .2s;
  border: 1px solid transparent; cursor: pointer;
}
.btn .ico { font-size: 1.05rem; transition: transform .25s; }
.btn--primary { background: var(--accent-1); color: var(--on-accent-1); box-shadow: 0 4px 0 var(--accent-1-deep); }
.btn--primary:hover { background: var(--accent-1-deep); color: var(--on-accent-1); transform: translateY(2px); box-shadow: 0 2px 0 var(--accent-1-deep); }
.btn--primary:hover .ico { transform: translateX(3px); }
.btn--outline { border-color: currentColor; background: transparent; }
.btn--outline:hover { background: var(--accent-1); color: var(--on-accent-1); border-color: var(--accent-1); }
/* Named for the dark-chrome design it came from, where "light" meant a pale
   button on a dark panel. It now means INVERTED: it paints the surface's own
   text colour and labels itself with the surface colour, so it stands off
   whatever it is sitting on — the five places it is used in the page content
   span the raised chrome and the folder panels. */
.btn--light { background: var(--on-surface); color: var(--surface); }
.btn--light:hover { background: var(--accent-1); color: var(--on-accent-1); }
/* A text button is a link, so it takes the surface's link colour rather than
   a fixed accent — brass-on-dark used to be hardcoded here and turned
   invisible the moment the chrome went light. */
.btn--text {
  padding: 0; background: none; color: var(--link);
  position: relative; gap: 0.4rem; text-transform: uppercase;
}
.btn--text:hover { color: var(--link-hover); }
.btn--text::after {
  content: ''; position: absolute; left: 0; right: 0; bottom: -3px; height: 2px;
  background: currentColor; transform: scaleX(0); transform-origin: left; transition: transform .3s ease;
}
.btn--text:hover::after { transform: scaleX(1); }
.btn--text:hover .ico { transform: translateX(3px); }
.btn--block { width: 100%; justify-content: center; }
.btn--lg { padding: 1.05rem 1.9rem; }

/* ============================================================
   Utilities (needed verbatim by the retained enquiry-form /
   google-reviews shortcode markup — see inc/enquiry-form.php,
   inc/google-reviews.php)
   ============================================================ */
.grid { display: grid; gap: 1.25rem; }
.col-2 { grid-template-columns: repeat(2, 1fr); }
.col-3 { grid-template-columns: repeat(3, 1fr); }

/* Two-column folder-panel layouts (text + photo, info + form). Ratios are
   per-section; the shared .split-2 base is what the mobile breakpoint
   collapses to a single column (see @media max-width:860px below) — kept
   as real classes instead of inline styles so that override can reach it. */
.split-2 { display: grid; gap: 2.5rem; }
.split-2--hero    { grid-template-columns: 1.1fr 0.9fr; align-items: center; }
.split-2--about   { grid-template-columns: 1fr 0.75fr; align-items: start; }
.split-2--contact { grid-template-columns: 0.8fr 1.2fr; align-items: start; }
.flex { display: flex; }
.items-center { align-items: center; }
.mt-1 { margin-top: 0.5rem; } .mt-2 { margin-top: 1rem; } .mt-3 { margin-top: 1.5rem; } .mt-4 { margin-top: 2rem; }
.mb-1 { margin-bottom: 0.5rem; } .mb-2 { margin-bottom: 1rem; } .mb-3 { margin-bottom: 1.5rem; } .mb-4 { margin-bottom: 2rem; }

/* "card" + "paper-stack" — the enquiry-form shortcode wraps itself in
   <div class="card paper-stack reveal ..." data-form-card>. Restyled
   here as a clipped index card with a stacked-paper shadow: plum up
   front, pine in the middle, slate at the back.

   Layering note: ::before/::after carry negative z-index, which the
   CSS painting order places *above* their own element's background but
   *below* its real content — so .card's own `background` is actually
   the bottom-most of the three fills, not the front one visible right
   behind the text. --plum goes on ::before (the less-negative, and so
   visually dominant, layer) for exactly that reason; .card's own
   background (--slate) only shows as the outermost sliver where the
   offset pseudo-elements don't reach.

   The card paints an accent, not a neutral, so it declares its own surface
   context (--surface/--on-surface, set in the grouped rule near the top) and
   every child below just reads --on-surface. That replaces the old hardcoded
   light-on-dark overrides, which assumed the accent would stay dark. */
.card {
  /* Read the layering note above before changing these three fills: this
     `background` is the BACK sliver, not the card face. The face is
     .paper-stack::before, which is what --surface/--on-surface are paired
     with, so the label and heading colours are measured against the fill the
     reader actually sees. */
  position: relative; background: var(--accent-4); color: var(--on-surface);
  clip-path: polygon(0 0, calc(100% - 20px) 0, 100% 20px, 100% 100%, 0 100%);
  padding: clamp(1.5rem, 2vw, 2.25rem);
}
.card .field > label,
.card.paper-stack :where(p, li),
.card.paper-stack :where(h1, h2, h3, h4) { color: var(--on-surface); }
.paper-stack { position: relative; }
.paper-stack::before,
.paper-stack::after {
  content: ''; position: absolute; inset: 0;
  clip-path: polygon(0 0, calc(100% - 20px) 0, 100% 20px, 100% 100%, 0 100%);
  z-index: -1;
}
.paper-stack::before { transform: translate(6px, 6px) rotate(0.6deg); background: var(--accent-2); } /* the card face */
.paper-stack::after { transform: translate(12px, 11px) rotate(-0.5deg); z-index: -2; opacity: 0.75; background: var(--accent-3); }

/* ============================================================
   Forms — required verbatim by inc/enquiry-form.php
   ============================================================ */
.field { display: flex; flex-direction: column; gap: 0.5rem; }
.field > label { font-family: var(--mono); font-weight: 700; font-size: 0.72rem; letter-spacing: 0.08em; text-transform: uppercase; color: var(--on-surface); }
/* Inputs are their own surface, not part of whichever card they sit on: they
   declare the card/input pair so the value the visitor types is always the
   page's body-text colour on the light input fill, whatever accent the
   surrounding card is painted with. */
.field input, .field select, .field textarea {
  width: 100%; background: var(--surface); color: var(--on-surface);
  border: 1px solid var(--hairline-strong); border-radius: 2px;
  padding: 0.8rem 1rem; font-size: 1rem; line-height: 1.4;
  transition: border-color .2s, box-shadow .2s;
}
.field textarea { resize: vertical; min-height: 130px; }
.field input::placeholder, .field textarea::placeholder { color: var(--text-muted); }
.field input:focus, .field select:focus, .field textarea:focus {
  outline: none; border-color: var(--accent-1); box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent-1) 22%, transparent);
}
.field--select { position: relative; }
.field select { appearance: none; -webkit-appearance: none; cursor: pointer; padding-right: 2.25rem; color: var(--on-surface); text-overflow: ellipsis; }
.field--select .ico { position: absolute; right: 0.8rem; bottom: 0.85rem; pointer-events: none; color: var(--text-muted); }
.field.invalid input, .field.invalid select, .field.invalid textarea { border-color: var(--accent-1); box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent-1) 18%, transparent); }
.field__error { font-size: 0.78rem; color: var(--accent-1-deep); display: none; align-items: center; gap: 0.3rem; }
.field.invalid .field__error { display: flex; }
.form-success { display: flex; flex-direction: column; align-items: flex-start; gap: 1rem; }
.form-success[hidden] { display: none; }

/* The enquiry form's fixed inline spacing (mt-3, field gaps, textarea
   height) reads as too tall for a single-column "Get in Touch" folder.
   Tighten it here rather than touching the shared plugin markup, which
   the classic theme also relies on at its own (taller) spacing. Some of
   the spacing being trimmed is set via inline style="" in the plugin
   markup (the title-divider wrapper and the submit-row padding-top),
   which needs !important to out-rank. */
[data-form-card] { padding: clamp(1.1rem, 1.6vw, 1.5rem); }
[data-form-card] > div:first-child { padding-bottom: 0.6rem !important; margin-bottom: 0.9rem !important; }
[data-form-card] > div:first-child h2 { margin: 0; }
.enquiry-form .field { gap: 0.3rem; }
.enquiry-form .field input,
.enquiry-form .field select,
.enquiry-form .field textarea { padding: 0.55rem 0.85rem; font-size: 0.9rem; }
.enquiry-form .field--select .ico { bottom: 0.6rem; }
.enquiry-form .field textarea { min-height: 70px; }
.enquiry-form .grid.col-2 { gap: 0.9rem !important; }
.enquiry-form .mt-3 { margin-top: 0.75rem; }
.enquiry-form > .mt-3:not(.field) { padding-top: 1rem !important; }

/* core wraps a stray <p> around the shortcode in some contexts */
.cab-main .wp-block-shortcode { margin: 0; }
.cab-main .wp-block-group > .wp-block-shortcode:empty { display: none; }

/* ============================================================
   Reveal — papers settling into place as folders open
   ============================================================ */
.reveal { opacity: 0; transform: translateY(16px) rotate(-0.6deg); transition: opacity .6s ease, transform .6s cubic-bezier(.2,.7,.3,1); }
.reveal.is-visible { opacity: 1; transform: none; }
.reveal-d1 { transition-delay: .08s; }
.reveal-d2 { transition-delay: .16s; }
.reveal-d3 { transition-delay: .24s; }
.reveal-d4 { transition-delay: .32s; }
@media (prefers-reduced-motion: reduce) {
  .reveal { opacity: 1; transform: none; transition: none; }
  html { scroll-behavior: auto; }
}

/* ============================================================
   Rail — sticky index nav (the drawer's label rail)
   ============================================================ */
/* position:sticky lives on the header wrapper WordPress generates around
   every template part (<header class="wp-block-template-part">), not on
   .rail itself. .rail is that header's only in-flow content, so the
   header box auto-sizes to exactly .rail's height — leaving position:sticky
   zero "runway" inside its containing block to stick within, which makes
   it behave like position:static from the very first pixel of scroll.
   Sticking the taller, full-page-height wrapper instead gives it real
   room to work with. */
header.wp-block-template-part:has(> .rail) { position: sticky; top: 0; z-index: 90; }
.rail {
  height: var(--rail-h);
  /* Opaque, not a translucent wash: a see-through rail blended whatever
     scrolled underneath into the tab colours, so the contrast of the tab
     labels changed as the page moved. */
  background: var(--surface-raised);
  border-bottom: 1px solid var(--hairline);
}
/* Overrides the standard .container max-width this element also carries
   (see --rail-container-max above) — the rail needs more width than body
   copy does, not the clamp(16px,5vw,40px) side padding, so only max-width
   is touched here. */
.rail__inner.container { max-width: var(--rail-container-max); }
.rail__inner { height: 100%; display: flex; align-items: stretch; justify-content: space-between; gap: 1.25rem; }
.rail__brand { display: inline-flex; align-items: center; gap: 0.6rem; align-self: center; }
.rail__brand-mark { display: block; height: 50px; width: auto; }
.rail__brand-mark svg { height: 100%; width: auto; display: block; }
.rail__brand-mark svg path { fill: var(--accent-1); }
.rail__brand-word { font-family: var(--mono); font-size: 0.72rem; letter-spacing: 0.14em; text-transform: uppercase; color: var(--text-muted); }

/* ---- Folder-tab cascade — the nav bar itself ----
   Modelled on a real staggered file-folder cut: instead of a flat row of
   equal-height links, each tab is its folder's own coloured card with a
   folder-tab notch (same clip-path language as .folder__flag), and the
   notches sit at alternating heights so the row reads as a fanned stack
   of folders rather than a conventional menu. Every tab keeps its colour
   all the time (not just on hover/active) — that constant colour is the
   whole point of the reference image this is built from. */
/* flex: 1 1 auto claims the row's own share of the widened rail container
   (see --rail-container-max) instead of leaving that space as a gap
   justify-content:space-between would otherwise put between the brand,
   the tabs and the CTA — tabs sit snug after the brand, with the CTA
   pinned to the right. overflow-x:auto still gives it a real minimum
   size of 0 (not its unshrunk content width), so on viewports too narrow
   even for the widened container it falls back to its own horizontal
   scroll instead of forcing the brand/CTA out of view. */
.tabrow { display: flex; flex: 1 1 auto; align-items: flex-end; height: 100%; gap: 3px; overflow-x: auto; scrollbar-width: none; padding-top: 10px; }
.tabrow::-webkit-scrollbar { display: none; }
.tabrow__tab {
  display: inline-flex; align-items: flex-start; gap: 0.4rem; white-space: nowrap;
  padding: 0.6rem 1rem 0.65rem 1.5rem;
  clip-path: polygon(0 100%, 0 26px, 20px 0, 100% 0, 100% 100%);
  font-family: var(--mono); font-weight: 700; font-size: 0.66rem; letter-spacing: 0.07em; text-transform: uppercase;
  color: var(--tab-ink, var(--on-accent-1)); background: var(--tab-accent, var(--accent-1));
  box-shadow: 0 4px 10px rgba(0,0,0,0.18);
  transition: transform .2s ease, box-shadow .2s ease, filter .2s ease;
}
/* three repeating cut-heights so consecutive folders visibly stagger,
   the way real hanging-folder tabs are cut at different positions so
   every label stays readable in the stack */
.tabrow__tab:nth-child(3n+1) { height: 58%; }
.tabrow__tab:nth-child(3n+2) { height: 78%; }
.tabrow__tab:nth-child(3n)   { height: 100%; }
.tabrow__num { opacity: 0.75; }
.tabrow__tab:hover { transform: translateY(-4px); filter: brightness(1.08); }
.tabrow__tab.is-active { transform: translateY(-6px); box-shadow: 0 -5px 12px rgba(0,0,0,0.18); }

/* ---- Numbered rail, hover-to-reveal ----
   11 hanging-folder tabs is too many to show fully labelled in one row,
   even in the widened rail container above. On pointer:fine devices —
   real mice, where hovering to "peek" a label costs nothing — collapse
   every tab to just its folder number and reveal the label on hover,
   keyboard focus, or when scrollspy marks it .is-active (setActiveRailLink
   in cabinet.js already toggles that class; no JS change needed here).
   Touch/no-hover devices are deliberately excluded: a tap there commits to
   navigation immediately, so there's no safe way to preview a label before
   following the link — they keep the always-visible label above instead. */
@media (hover: hover) and (pointer: fine) {
  .tabrow__tab { gap: 0; }
  .tabrow__num { opacity: 1; font-size: 0.74rem; }
  .tabrow__label {
    display: inline-block; max-width: 0; margin-left: 0; opacity: 0; overflow: hidden;
    transition: max-width .3s ease, margin-left .3s ease, opacity .2s ease;
  }
  .tabrow__tab:hover .tabrow__label,
  .tabrow__tab:focus-visible .tabrow__label,
  .tabrow__tab.is-active .tabrow__label {
    max-width: 220px; margin-left: 0.5rem; opacity: 1; transition-delay: 0s, 0s, .05s;
  }
}
/* The five accent modifiers. The class names are historical (rust/pine/
   brass/plum/slate) and are baked into header.html, the patterns and the
   page content, so they stay — but each now resolves to a numbered palette
   accent plus the text colour measured against it, instead of to a material
   colour that doubled as body text elsewhere. There are five class names and
   four palette accents, so --slate shares the blueberry accent; add a fifth
   slug in theme.json if the rotation ever needs another colour. */
.tabrow__tab--rust  { --tab-accent: var(--accent-1); --tab-ink: var(--on-accent-1); }
.tabrow__tab--pine  { --tab-accent: var(--accent-2); --tab-ink: var(--on-accent-2); }
.tabrow__tab--brass { --tab-accent: var(--accent-3); --tab-ink: var(--on-accent-3); }
.tabrow__tab--plum  { --tab-accent: var(--accent-4); --tab-ink: var(--on-accent-4); }
.tabrow__tab--slate { --tab-accent: var(--accent-3); --tab-ink: var(--on-accent-3); }
.rail__actions { display: flex; align-items: center; gap: 0.65rem; align-self: center; }
.rail__toggle { display: none; width: 42px; height: 42px; align-items: center; justify-content: center; color: var(--accent-1); }
.rail__toggle .ico { font-size: 1.6rem; }

/* Mobile slide-in rail-menu */
.rail-menu-scrim { position: fixed; inset: 0; background: color-mix(in srgb, var(--text-page) 55%, transparent); opacity: 0; visibility: hidden; transition: opacity .3s; z-index: 95; }
.rail-menu-scrim.is-open { opacity: 1; visibility: visible; }
.rail-menu {
  position: fixed; top: 0; right: 0; height: 100%; width: min(86vw, 360px);
  background: var(--surface-raised); z-index: 100; transform: translateX(100%);
  transition: transform .35s cubic-bezier(.4,0,.2,1); display: flex; flex-direction: column;
  box-shadow: -12px 0 40px rgba(0,0,0,0.22); padding: 1.25rem; border-left: 1px solid var(--hairline);
}
.rail-menu.is-open { transform: translateX(0); }
.rail-menu__top { display: flex; align-items: center; justify-content: space-between; margin-bottom: 1.5rem; }
.rail-menu__close { width: 42px; height: 42px; display: inline-flex; align-items: center; justify-content: center; color: var(--accent-1); }
.rail-menu__close .ico { font-size: 1.6rem; }
.rail-menu__links { display: flex; flex-direction: column; gap: 0.1rem; overflow-y: auto; }
.rail-menu__link {
  font-family: var(--mono); font-weight: 700; font-size: 0.85rem; letter-spacing: 0.06em; text-transform: uppercase;
  color: var(--on-surface); padding: 0.9rem 0.4rem 0.9rem 0.9rem; border-bottom: 1px solid var(--hairline);
  border-left: 3px solid var(--tab-accent, var(--hairline-strong));
  display: flex; align-items: center; justify-content: space-between;
}
.rail-menu__link .ico { color: var(--accent-1); }
.rail-menu__link--rust  { --tab-accent: var(--accent-1); }
.rail-menu__link--pine  { --tab-accent: var(--accent-2); }
.rail-menu__link--brass { --tab-accent: var(--accent-3); }
.rail-menu__link--plum  { --tab-accent: var(--accent-4); }
.rail-menu__link--slate { --tab-accent: var(--accent-3); }
.rail-menu__foot { margin-top: auto; padding-top: 1.25rem; }

/* ============================================================
   Footer — the bottom rail of the cabinet
   ============================================================ */
.foot { background: var(--surface-raised); border-top: 1px solid var(--hairline); }
.foot__grid { display: grid; grid-template-columns: 1.4fr 1fr 1fr; gap: 3rem; padding-block: clamp(3rem, 5vw, 4.5rem); }
.foot__logo { display: block; height: 42px; width: auto; margin-bottom: 1.1rem; }
.foot__logo svg { height: 100%; width: auto; display: block; }
.foot__logo svg path { fill: var(--accent-1); }
.foot__tag { color: var(--text-muted); max-width: 34ch; margin-bottom: 1.5rem; }
.foot__social { display: flex; gap: 0.75rem; }
.social-btn { width: 42px; height: 42px; border: 1px solid var(--hairline-strong); border-radius: 2px; display: inline-flex; align-items: center; justify-content: center; color: var(--on-surface); transition: background .2s, color .2s, border-color .2s; }
.social-btn svg { width: 18px; height: 18px; stroke: currentColor; }
.foot__social .social-btn:hover { background: var(--accent-1); color: var(--on-accent-1); border-color: var(--accent-1); }
/* The "Get in Touch" folder reuses .foot__social inside a folder panel. The
   base rule above already tracks whichever surface it lands on, so only the
   hover fill is restated here. */
.folder__panel-inner .social-btn:hover { background: var(--accent-1); color: var(--on-accent-1); border-color: var(--accent-1); }
.foot__col h4 { font-family: var(--mono); font-weight: 700; font-size: 0.7rem; letter-spacing: 0.1em; text-transform: uppercase; color: var(--text-muted); margin-bottom: 1.1rem; }
.foot__col ul { list-style: none; padding: 0; margin: 0; display: flex; flex-direction: column; gap: 0.7rem; }
.foot__col a { color: var(--link); font-size: 0.95rem; transition: color .2s; }
.foot__col a:hover { color: var(--link-hover); }
.foot__bar { border-top: 1px solid var(--hairline); padding-block: 1.5rem; display: flex; justify-content: space-between; gap: 1rem; flex-wrap: wrap; }
.foot__bar p { font-size: 0.76rem; color: var(--text-muted); margin: 0; font-family: var(--mono); }

/* ============================================================
   THE DRAWER — one-page folder cabinet
   ============================================================ */
.drawer {
  /* Deliberately no native CSS scroll-snap here: folders swing between
     a ~100px closed tab and a very tall open panel, and the browser
     re-resolves snap points continuously as that height changes —
     which fights an in-flight scroll and produces exactly the kind
     of jump this design is trying to avoid. "Scroll capturing" is
     instead handled entirely in JS (cabinet.js pickActiveByScroll),
     which is stable under changing content height.

     overflow-anchor is switched off for the same reason: as one
     folder collapses and another (a very different height) expands
     above the viewport, the browser's scroll-anchoring would yank
     the scroll position to compensate, which then feeds back into
     pickActiveByScroll and skips folders entirely. */
  overflow-anchor: none;
}
.drawer::before {
  /* top lip of the drawer, purely decorative — a flat band rather than the
     fade it used to be, so it can't darken the colour underneath it */
  content: ''; display: block; height: 6px;
  background: var(--hairline);
}

.folder {
  /* +24px on top of the rail height: .folder__flag pokes up 15px above
     this box's own top edge (see .folder__flag below), so aligning
     scroll-margin exactly to the rail leaves the flag's top half
     tucked under the sticky rail. The extra px clears the flag fully
     plus a little breathing room. */
  scroll-margin-top: calc(var(--rail-h) + 24px);
  border-bottom: 1px solid var(--hairline);
  overflow-anchor: none;
}

/* ---- Tab (always visible, click to toggle) ---- */
.folder__tab {
  position: relative; width: 100%; text-align: left;
  display: flex; align-items: center; gap: 1.1rem; flex-wrap: wrap;
  padding: 1.35rem clamp(1.25rem, 4vw, 2.75rem) 1.35rem clamp(1.25rem, 4vw, 2.75rem);
  background: var(--surface);
  transition: background .25s ease;
}
/* Hover darkens the row's own surface by a fixed amount rather than swapping
   in a second named colour, so alternating rows stay distinguishable however
   close together the client sets the two background slugs. */
.folder__tab:hover { background: color-mix(in srgb, var(--surface), var(--on-surface) 7%); }

/* the little flag that pokes up above the tab row like a real
   hanging-folder tab — this is the "originality" hook the reference
   image is going for, reinterpreted with our own accent set */
.folder__flag {
  position: absolute; left: clamp(1.25rem, 4vw, 2.75rem); top: -15px;
  display: inline-flex; align-items: center; gap: 0.5rem;
  padding: 0.4rem 1rem 0.4rem 0.85rem;
  font-family: var(--mono); font-weight: 700; font-size: 0.68rem; letter-spacing: 0.13em; text-transform: uppercase;
  clip-path: polygon(0 100%, 0 22%, 9% 0, 100% 0, 100% 100%);
  box-shadow: 0 -2px 0 rgba(0,0,0,0.3), 0 3px 10px rgba(0,0,0,0.35);
}
.folder--rust .folder__flag  { background: var(--accent-1); color: var(--on-accent-1); --tab-accent: var(--accent-1); }
.folder--pine .folder__flag  { background: var(--accent-2); color: var(--on-accent-2); --tab-accent: var(--accent-2); }
.folder--brass .folder__flag { background: var(--accent-3); color: var(--on-accent-3); --tab-accent: var(--accent-3); }
.folder--plum .folder__flag  { background: var(--accent-4); color: var(--on-accent-4); --tab-accent: var(--accent-4); }
.folder--slate .folder__flag { background: var(--accent-3); color: var(--on-accent-3); --tab-accent: var(--accent-3); }

.folder__num { font-family: var(--mono); font-size: 0.68rem; opacity: 0.85; }

.folder__tab-body { flex: 1; min-width: 220px; display: flex; align-items: baseline; gap: 0.9rem; flex-wrap: wrap; padding-top: 0.4rem; }
.folder__peek {
  font-family: var(--display); font-weight: 600; color: var(--text-heading);
  font-size: clamp(1.15rem, 1rem + 1vw, 1.6rem);
}
.folder__hint { font-family: var(--mono); font-size: 0.76rem; color: var(--text-muted); }

.folder__pull {
  flex: none; width: 34px; height: 34px; border-radius: 50%;
  border: 1px solid var(--hairline-strong); display: grid; place-items: center;
  color: var(--on-surface); transition: transform .35s ease, background .2s ease, border-color .2s ease;
}
.folder__pull .ico { font-size: 1rem; transition: transform .35s ease; }
.folder.is-open .folder__pull { transform: rotate(45deg); background: var(--accent-1); color: var(--on-accent-1); border-color: var(--accent-1); }

/* ---- Panel (the paper that slides out) ----
   Uses the grid-template-rows 0fr/1fr expand trick: robust with
   variable content height, no JS measuring required. */
.folder__panel {
  display: grid;
  /* No-JS / slow-JS default: content stays visible and readable.
     Once cabinet.js boots it adds .js-cabinet to <html> and takes
     over — see the two rules below. */
  grid-template-rows: 1fr;
  transition: grid-template-rows .55s cubic-bezier(.4,0,.2,1);
}
.js-cabinet .folder__panel { grid-template-rows: 0fr; }
.js-cabinet .folder.is-open .folder__panel { grid-template-rows: 1fr; }
.folder__panel-clip { overflow: hidden; }
.folder__panel-inner {
  position: relative;
  /* One flat fill. This used to be a top-to-bottom gradient between two
     palette slugs, which meant the contrast of the copy on it changed down
     the length of the panel, and neither slug on its own told the client what
     the panel would actually look like. */
  background: var(--surface-panel);
  color: var(--on-surface);
  padding: clamp(1.75rem, 4vw, 3rem) clamp(1.25rem, 4vw, 2.75rem) clamp(2.25rem, 5vw, 3.5rem);
  border-top: 4px solid var(--tab-accent, var(--accent-1));
  box-shadow: inset 0 12px 24px -18px rgba(0,0,0,0.25);
}
/* Paper grain. A texture rather than a colour ramp: a 3px dot lattice in the
   panel's own text colour at low opacity, so it reads as tooth on the stock
   without shifting the fill toward a second colour the way the old gradient
   did. Drawn in --on-surface rather than a fixed black so it stays visible if
   the client ever picks a dark panel. */
.folder__panel-inner::before {
  content: ''; position: absolute; inset: 0; pointer-events: none; opacity: 0.07;
  background-image: radial-gradient(circle at 1px 1px, var(--on-surface) 1px, transparent 0);
  background-size: 3px 3px;
}
.folder__panel-inner > * { position: relative; }

/* brass rivets along the panel's top edge */
.folder__rivets { display: flex; gap: 1.4rem; padding-bottom: 1.4rem; }
.folder__rivets span {
  width: 8px; height: 8px; border-radius: 50%;
  background: var(--accent-1);
  box-shadow: 0 1px 2px rgba(0,0,0,0.25);
}

/* Editorial content defaults inside an open panel (manila paper) */
.folder__panel-inner :where(h1,h2,h3,h4) { color: var(--text-heading); font-family: var(--display); }
.folder__panel-inner a:not(.btn):not(.social-btn) { color: var(--link); text-decoration: underline; text-underline-offset: 3px; text-decoration-color: color-mix(in srgb, currentColor 40%, transparent); }
.folder__panel-inner a:not(.btn):not(.social-btn):hover { color: var(--link-hover); text-decoration-color: currentColor; }
.folder__panel-inner :where(p,li) { color: var(--text-muted); }

/* ============================================================
   File cards — the "case file" grid used for services
   ============================================================ */
.file-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(230px, 1fr)); gap: 1.4rem; }
.file-card {
  position: relative; background: var(--surface-card); color: var(--on-surface);
  padding: 1.75rem 1.5rem 1.6rem;
  clip-path: polygon(0 0, calc(100% - 20px) 0, 100% 20px, 100% 100%, 0 100%);
  box-shadow: var(--shadow-soft);
  transition: transform .28s ease, box-shadow .28s ease;
  display: flex; flex-direction: column; gap: 0.85rem; height: 100%;
}
.file-card:hover { transform: translateY(-5px) rotate(-0.5deg); box-shadow: var(--shadow-drop); }
.file-card__chip {
  width: 44px; height: 44px; border-radius: 3px; display: inline-flex; align-items: center; justify-content: center;
  background: var(--tab-accent, var(--accent-1)); color: var(--tab-ink, var(--on-accent-1)); font-size: 1.4rem; flex: none;
}
.file-card--rust  { --tab-accent: var(--accent-1); --tab-ink: var(--on-accent-1); }
.file-card--pine  { --tab-accent: var(--accent-2); --tab-ink: var(--on-accent-2); }
.file-card--brass { --tab-accent: var(--accent-3); --tab-ink: var(--on-accent-3); }
.file-card--plum  { --tab-accent: var(--accent-4); --tab-ink: var(--on-accent-4); }
.file-card--slate { --tab-accent: var(--accent-3); --tab-ink: var(--on-accent-3); }
.file-card h3 { margin: 0; }
.file-card p { margin: 0; flex: 1; color: var(--text-muted); }
.file-card .btn--text { align-self: flex-start; }
.file-card.has-link-cover { position: relative; }
.file-card .link-cover { position: absolute; inset: 0; z-index: 1; }

/* ============================================================
   Photo clip — a taped-in photograph, our alternative to a plain
   framed image: paper mount, slight rotation, a strip of washi
   tape pinning it to the page, mono caption underneath.
   ============================================================ */
.photo-clip {
  position: relative; display: inline-block; width: 100%;
  background: var(--surface-card); padding: 10px 10px 36px;
  box-shadow: var(--shadow-soft); rotate: -1.1deg;
}
.photo-clip img { display: block; width: 100%; height: auto; filter: sepia(0.12) contrast(1.05); }
.photo-clip figure { margin: 0; }
.photo-clip__caption {
  position: absolute; left: 0; right: 0; bottom: 10px; text-align: center;
  font-family: var(--mono); font-size: 0.64rem; letter-spacing: 0.08em; text-transform: uppercase; color: var(--text-muted);
}
.photo-clip__tape {
  position: absolute; top: -13px; left: 50%; translate: -50% 0; width: 92px; height: 26px;
  background: color-mix(in srgb, var(--accent-2) 60%, transparent); border: 1px solid rgba(0,0,0,0.05);
  rotate: -3deg; box-shadow: 0 3px 6px rgba(0,0,0,0.2);
}

/* ============================================================
   Credentials strip (About folder)
   ============================================================ */
.cred-list { display: flex; flex-direction: column; }
.cred { display: grid; grid-template-columns: auto 1fr auto; gap: 1.1rem 1.4rem; align-items: center; padding-block: 1.15rem; border-bottom: 1px dashed var(--hairline-strong); }
.cred:last-child { border-bottom: 0; }
.cred__icon { color: var(--accent-1); font-size: 1.9rem; }
.cred__k { display: block; font-family: var(--mono); font-size: 0.65rem; letter-spacing: 0.1em; text-transform: uppercase; color: var(--text-muted); margin-bottom: 0.2rem; }
.cred__v { font-family: var(--mono); font-size: 1rem; color: var(--on-surface); display: inline-flex; align-items: center; }
/* SAIT / SARS affiliation logos under the credential rows (About folder).
   White chips, not var(--paper): the SAIT file is a JPEG on pure white,
   so anything but #fff shows its bounding box. */
.cred-logos { display: flex; flex-wrap: wrap; gap: 0.9rem; padding-top: 1.15rem; }
.cred-logo { background: #fff; border: 1px solid var(--hairline); padding: 0.55rem 0.9rem; display: inline-flex; align-items: center; }
.cred-logo img { display: block; height: 40px; width: auto; }

/* ============================================================
   Docket steps ("how it works")
   ============================================================ */
.docket { counter-reset: docket; display: grid; gap: 0; }
.docket-step { display: grid; grid-template-columns: auto 1fr; gap: 1.25rem; align-items: start; padding-block: 1.35rem; border-bottom: 1px dashed var(--hairline-strong); }
.docket-step:last-child { border-bottom: 0; }
.docket-step__num {
  counter-increment: docket; font-family: var(--mono); font-weight: 700; font-size: 0.95rem; color: var(--accent-1);
  width: 46px; height: 46px; display: grid; place-items: center; border: 1px dashed var(--hairline-strong); border-radius: 50%;
}
.docket-step__num::before { content: "N\B0" counter(docket, decimal-leading-zero); }
.docket-step h4 { margin: 0 0 0.35rem; }
.docket-step p { margin: 0; color: var(--text-muted); }

/* ============================================================
   FAQ slips
   ============================================================ */
.faq-slips { display: flex; flex-direction: column; }
.faq-slip { border-bottom: 1px solid var(--hairline); }
.faq-slip:first-child { border-top: 1px solid var(--hairline); }
.faq-slip__q {
  width: 100%; display: flex; align-items: center; justify-content: space-between; gap: 1rem;
  padding: 1.3rem 0.15rem; text-align: left; font-family: var(--display); font-weight: 600; font-size: 1.08rem; color: var(--on-surface);
}
.faq-slip__q .ico { color: var(--accent-1); transition: transform .3s; flex: none; }
.faq-slip.is-open .faq-slip__q .ico { transform: rotate(45deg); }
.faq-slip__a { display: grid; grid-template-rows: 1fr; transition: grid-template-rows .4s ease; }
.js-cabinet .faq-slip__a { grid-template-rows: 0fr; }
.js-cabinet .faq-slip.is-open .faq-slip__a { grid-template-rows: 1fr; }
.faq-slip__a-clip { overflow: hidden; }
.faq-slip__a p { padding: 0 0.15rem 1.3rem; color: var(--text-muted); max-width: 68ch; margin: 0; }

/* ============================================================
   Stamp CTA — an ink-stamp accent instead of a plain circle cutout
   ============================================================ */
.stamp-cta {
  position: relative; background: var(--surface-raised); color: var(--on-surface);
  padding: clamp(2.25rem, 5vw, 3.5rem); overflow: hidden; border: 1px solid var(--hairline);
  /* The mark is taken out of flow, so the row has to leave its strip of the
     band empty by hand — otherwise the CTA button lands on top of it (the
     button is the last item of a space-between row, i.e. hard against the
     right padding edge, while the mark sits further right still). The gutter
     covers the mark plus the extra width the -14deg rotation adds, and drops
     to 0 in the <=680px block below where the mark is hidden. */
  --stamp-size: 128px;
  --stamp-gutter: calc(var(--stamp-size) + 1.5rem);
}
.stamp-cta__inner { display: flex; align-items: center; justify-content: space-between; gap: 2rem; flex-wrap: wrap; position: relative; z-index: 1; padding-right: var(--stamp-gutter); }
/* Let the copy column absorb the width the gutter takes away — it wraps its
   own lines instead of shoving the button onto a row of its own, so the band
   stays one line down to about the same width it did before the gutter. */
.stamp-cta__inner > :first-child { flex: 1 1 20rem; min-width: 0; }
.stamp-cta p { color: var(--text-muted); }
/* The eyebrow and heading used to carry their colours as inline styles in the
   page content (colour:var(--brass) / var(--paper)), which put palette
   decisions in the database where no contrast rule could reach them. They are
   set here instead; the inline styles have been stripped from the content. */
.stamp-cta .label { color: var(--accent-1); }
.stamp-cta :where(h1,h2,h3,h4) { color: var(--text-heading); }
.stamp-cta__mark {
  position: absolute; right: clamp(-10px, 2vw, 24px); top: 50%; translate: 0 -50%;
  width: var(--stamp-size); height: var(--stamp-size); border-radius: 50%; border: 3px dashed color-mix(in srgb, var(--accent-1) 40%, transparent);
  display: grid; place-items: center; rotate: -14deg; color: color-mix(in srgb, var(--accent-1) 55%, transparent);
  font-family: var(--mono); font-size: 0.62rem; letter-spacing: 0.18em; text-transform: uppercase; text-align: center;
  pointer-events: none;
}

/* ============================================================
   Google reviews — required verbatim by inc/google-reviews.php
   ============================================================ */
.gr-reviews {}
.gr-note { color: var(--text-muted); margin-bottom: 1.25rem; }
.gr-grid {}
.gr-card { background: var(--surface-card); color: var(--on-surface); padding: 1.5rem; clip-path: polygon(0 0, calc(100% - 16px) 0, 100% 16px, 100% 100%, 0 100%); display: flex; flex-direction: column; gap: .8rem; box-shadow: var(--shadow-soft); }
.gr-stars { letter-spacing: .15em; font-size: 1.05rem; line-height: 1; }
.gr-star { color: var(--hairline-strong); }
.gr-star.is-on { color: var(--accent-1); }
.gr-text { flex: 1; color: var(--text-muted); }
.gr-meta { font-size: .9rem; }
.gr-more { margin-top: 1.5rem; }

/* ============================================================
   Copy-to-clipboard button (used on the practitioner-number credential)
   ============================================================ */
.copy-btn { display: inline-flex; align-items: center; justify-content: center; width: 2.1rem; height: 2.1rem; margin-left: .5rem; vertical-align: middle; border: 0; border-radius: 2px; background: transparent; color: var(--accent-1); cursor: pointer; transition: background .2s, color .2s; }
.copy-btn:hover { background: color-mix(in srgb, var(--on-surface) 10%, transparent); }
.copy-btn .ico { font-size: 1rem; }
.copy-btn.is-copied { background: color-mix(in srgb, var(--accent-1) 14%, transparent); color: var(--accent-1-deep); }

/* Whole-card / whole-row links (core groups can't render as anchors) */
.has-link-cover { position: relative; }
.link-cover { position: absolute; inset: 0; z-index: 1; }

/* ============================================================
   Responsive
   ============================================================ */
@media (min-width: 861px) {
  /* Desktop only: give each folder a bit of breathing room from the
     next instead of sitting flush on the shared border-bottom. Mobile
     keeps folders flush — screen space is tighter there and the
     folder__flag already collapses to static/inline (see the 560px
     block below), so there's no flag-clearance reason to add it. */
  .folder + .folder { margin-top: 2.5rem; }
}
@media (max-width: 860px) {
  :root { --rail-h: 66px; }
  .tabrow, .rail__cta-desktop { display: none; }
  .rail__toggle { display: inline-flex; }
  .foot__grid { grid-template-columns: 1fr 1fr; gap: 2rem 1.5rem; }
  .foot__brand { grid-column: 1 / -1; }
  [data-form-card] { padding: 1.15rem; }
  .split-2 { grid-template-columns: 1fr; gap: 1.75rem; }
}
@media (max-width: 680px) {
  .col-3, .col-2 { grid-template-columns: 1fr; }
  .stamp-cta { --stamp-gutter: 0px; }
  .stamp-cta__inner { flex-direction: column; align-items: flex-start; }
  .stamp-cta__mark { display: none; }
  .file-card[style*="span 2"] { grid-column: auto !important; }
}
@media (max-width: 560px) {
  .foot__grid { grid-template-columns: 1fr; }
  .folder__flag { position: static; margin-bottom: 0.6rem; display: inline-flex; box-shadow: none; }
  .folder__tab { padding-top: 1.1rem; flex-direction: column; align-items: flex-start; }
  .folder__pull { position: absolute; top: 1.35rem; right: clamp(1.25rem, 4vw, 2.75rem); }
  .rail__brand-word { display: none; }
  .cred { grid-template-columns: auto 1fr; row-gap: 0.6rem; }
  .cred > a.btn { grid-column: 1 / -1; justify-self: start; }
  .cred > span:last-child:empty { display: none; }
}
