/*
Theme Name: Gallatin River
Theme URI: https://gallatin.nl
Author: Gallatin River B.V.
Description: Block theme for gallatin.nl. Warm paper ground, Outfit throughout, no page builder, no plugins beyond the multilingual layer.
Requires at least: 6.7
Tested up to: 7.0
Requires PHP: 8.2
Version: 0.1.0
License: GPL-2.0-or-later
License URI: https://www.gnu.org/licenses/gpl-2.0.html
Text Domain: gallatin
Tags: full-site-editing, blocks
*/

/* Everything structural lives in theme.json. This file carries the parts the
   block system cannot express: component styling, the header material, and
   the typographic detail that makes Outfit sit correctly at each size. */

/* ============================================================
   TYPE
   Outfit is geometric and wide, so tracking is set per size.
   A single letter-spacing value would be wrong at one end.
   ============================================================ */
body {
  -webkit-font-smoothing: antialiased;
  letter-spacing: .007em;
  /* clip, not hidden. overflow-x: hidden makes the body a scroll container,
     which silently kills position: sticky in every descendant. */
  overflow-x: clip;
}

/* The header is sticky, so anything else that sticks has to clear it. One
   number, declared once, rather than the same guess in three places. */
:root { --gr-header-h: 78px; }

h1, h2, h3, h4 { text-wrap: balance; }
p { text-wrap: pretty; }

.gr-display {
  font-size: clamp(2.75rem, 7vw, 5rem);
  line-height: 1.03;
  letter-spacing: -.048em;
  font-weight: 700;
}
.gr-eyebrow {
  font-size: .8125rem;
  letter-spacing: .11em;
  text-transform: uppercase;
  font-weight: 500;
  color: var(--wp--preset--color--ink-muted);
}

/* ============================================================
   HEADER
   Flat and solid, with a hairline that only appears once there
   is content underneath it.
   ============================================================ */
/* The header template part renders inside a wrapper div that is exactly the
   header's own height. A sticky element travels only within its parent, so the
   header had nowhere to stick and scrolled away. display: contents removes that
   box, making the header a direct child of the page flow. */
.wp-site-blocks > .wp-block-template-part:first-child { display: contents; }

.gr-header {
  position: sticky;
  top: 0;
  z-index: 40;
  background: var(--wp--preset--color--paper);
  border-bottom: 1px solid transparent;
  transition: border-color 220ms cubic-bezier(.32,.72,0,1);
}
.gr-header.is-scrolled { border-bottom-color: var(--wp--preset--color--hairline); }
.gr-header .wp-block-site-logo img { width: 56px; height: 56px; display: block; }
.gr-wordmark {
  margin: 0;
  font-weight: 500;
  letter-spacing: -.02em;
  font-size: 1.625rem;
  line-height: 1;
}
.gr-wordmark a { text-decoration: none; white-space: nowrap; }
.gr-nav a {
  font-size: .9375rem;
  font-weight: 420;
  letter-spacing: .002em;
  color: var(--wp--preset--color--ink-2);
  text-decoration: none;
}
.gr-nav a:hover { color: var(--wp--preset--color--ink); }

/* Below the breakpoint where the nav collapses to a toggle, the row holds
   logo, wordmark, toggle and button. At 375px that wants more width than
   there is, and a nowrap flex row answers by breaking the text inside each
   item instead. Buy the space back from the gaps and the button padding,
   and forbid the breaks, so the header stays one line deep. */
@media (max-width: 600px) {
  /* A 56px mark plus the wordmark at full size does not fit beside the toggle
     and the button on a phone. Both come down rather than the row wrapping. */
  .gr-header .wp-block-site-logo img { width: 40px; height: 40px; }
  .gr-wordmark { font-size: 1.25rem; }
  .gr-header .wp-block-group.alignwide { gap: 1rem; }
  .gr-header .wp-block-group.alignwide > .wp-block-group:last-child { gap: 1rem; }
  .gr-wordmark,
  .gr-wordmark a,
  .gr-header .wp-block-button__link { white-space: nowrap; }
  .gr-header .wp-block-button__link { padding-inline: .85rem; letter-spacing: .07em; }
}
/* On the narrow phones the wordmark is what has to give. The logo is still
   a link home and carries the site name as its alt text, so nothing is lost
   but the repetition. */
@media (max-width: 360px) {
  .gr-wordmark { display: none; }
}

/* ============================================================
   BUTTONS
   One shape across the system: square, small radius, set in caps.
   Caps read larger than lowercase, so the size comes down and the
   tracking goes positive.
   ============================================================ */
.wp-block-button__link {
  font-size: .8125rem;
  font-weight: 500;
  letter-spacing: .085em;
  text-transform: uppercase;
  padding: .72rem 1.15rem;
  border-radius: 9px;
  transition: background-color 220ms cubic-bezier(.32,.72,0,1), transform 90ms cubic-bezier(.32,.72,0,1);
}
.wp-block-button__link:active { transform: scale(.98); }
.gr-btn-lg .wp-block-button__link { padding: .9rem 1.4rem; font-size: .875rem; }
.is-style-outline > .wp-block-button__link {
  border: 1px solid var(--wp--preset--color--hairline);
  color: var(--wp--preset--color--ink);
}
.is-style-outline > .wp-block-button__link:hover { background: var(--wp--preset--color--paper-2); }

/* Short pages should still fill the window: the footer sits at the bottom
   rather than halfway up with page background beneath it. */
.wp-site-blocks {
  display: flex;
  flex-direction: column;
  min-height: 100svh;
}
.wp-site-blocks > main { flex: 1 0 auto; }
.wp-site-blocks > .wp-block-template-part:last-child { margin-top: auto; }

/* ============================================================
   FOOTER
   ============================================================ */
/* WordPress puts a block gap between the top level blocks, which left a strip
   of page background between the last section and the footer. A full bleed
   band should run straight into it. */
.wp-site-blocks > .wp-block-template-part:last-child { margin-block-start: 0; }

.gr-footer { border-top: 1px solid var(--wp--preset--color--hairline); }
.gr-footer .wp-block-site-logo img { width: 44px; height: 44px; display: block; }
.gr-footer .gr-wordmark { font-size: 1.375rem; }
.gr-footer a { text-decoration: none; }
.gr-footer a:hover { color: var(--wp--preset--color--ink); }
.gr-footer-heading {
  font-size: .8125rem;
  letter-spacing: .09em;
  text-transform: uppercase;
  font-weight: 500;
  color: var(--wp--preset--color--ink-muted);
}
.gr-green {
  font-size: .8125rem;
  color: var(--wp--preset--color--ink-muted);
}
.gr-green a {
  color: inherit;
  text-decoration: underline;
  text-underline-offset: 2px;
  text-decoration-color: var(--wp--preset--color--hairline);
}
.gr-green a:hover { color: var(--wp--preset--color--ink); text-decoration-color: currentColor; }

/* ============================================================
   ACCESSIBILITY
   ============================================================ */
:where(a, button):focus-visible {
  outline: 2px solid var(--wp--preset--color--indigo);
  outline-offset: 3px;
  border-radius: 4px;
}
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { transition-duration: 150ms !important; animation-duration: 1ms !important; }
  .wp-block-button__link:active { transform: none !important; }
}

/* Footer lists are navigation, not prose, so no markers or indent. */
.gr-footer ul {
  list-style: none;
  margin: 0;
  padding: 0;
}
.gr-footer li a { color: var(--wp--preset--color--ink-2); font-size: .9375rem; }

/* The site logo is a mark, not an image block: no caption, no rounding. */
.gr-header .wp-block-site-logo a,
.gr-footer .wp-block-site-logo a { display: block; line-height: 0; }

/* ============================================================
   HOMEPAGE: HERO
   ============================================================ */
.gr-hero { padding-block: var(--wp--preset--spacing--70) var(--wp--preset--spacing--80); }
/* the hero reads from the left edge of the wide container, so every child
   is capped and pushed left rather than centred in the content column */
.gr-hero > * { max-width: 44rem; margin-inline: 0 auto; }
/* No narrower cap on the lede. A constrained layout centres a child that is
   narrower than the content column, so a 34rem lede under a 44rem headline sat
   indented from it. Same fault as the indigo band. */

/* ============================================================
   HOMEPAGE: THE EXPANDING PANEL
   Rounded and inset on arrival, full bleed by the time you leave it.
   Only inset and radius change, so nothing reflows the page around it.
   ============================================================ */
.gr-expand { position: relative; height: 300vh; }
/* The closing variant, used as a hero. It arrives full bleed and gains its
   inset on the way out. Shorter travel than the opening one, because a hero
   that holds you for three screens before the page starts is a toll gate. */
.gr-expand-in { height: 200vh; }
/* The sticky box starts below the header rather than at the viewport top.
   Otherwise the panel's top margin opens underneath the header and only the
   left, right and bottom edges appear to inset. */
.gr-expand-in .gr-expand-sticky {
  top: var(--gr-header-h);
  height: calc(100svh - var(--gr-header-h));
}
.gr-expand-in .gr-panel { height: calc(100svh - var(--gr-header-h) - var(--padY) * 2); }
.gr-expand-sticky {
  position: sticky;
  top: 0;
  height: 100svh;
  display: grid;
  place-items: center;
  overflow: hidden;
}
.gr-panel {
  --pad: clamp(1rem, 4vw, 3.5rem);
  --padY: 3rem;
  --r: 22px;
  position: relative;
  width: calc(100vw - var(--pad) * 2);
  height: calc(100svh - var(--padY) * 2);
  background: var(--wp--preset--color--deep);
  color: #EFEFF3;
  border-radius: var(--r);
  display: grid;
  place-items: center;
  overflow: hidden;
  padding: calc(var(--gr-header-h) + clamp(1rem, 4vh, 2.5rem)) clamp(1.5rem, 5vw, 4rem) clamp(1rem, 4vh, 2.5rem);
  will-change: width, height, border-radius;
}
.gr-panel-copy {
  position: relative;
  z-index: 3;
  max-width: 54rem;
  align-self: center;
  text-align: center;
}
/* a soft pool of the panel colour, so bubbles can drift under the
   headline without it having to compete with them */
.gr-panel-copy::before {
  content: "";
  position: absolute;
  inset: -14% -12%;
  z-index: -1;
  pointer-events: none;
  background: radial-gradient(58% 56% at 50% 50%, var(--wp--preset--color--deep) 62%, transparent 100%);
}
.gr-panel-copy h1,
.gr-panel-copy h2 { color: #fff; font-size: clamp(2.4rem, 5.4vw, 4.25rem); line-height: 1.03; letter-spacing: -.034em; font-weight: 700; }
/* Used as a hero, the panel carries the eyebrow and an outline button, and
   both need the light treatment the dark ground asks for. */
.gr-crumb-on-dark {
  justify-content: center;
  margin: 0 0 var(--wp--preset--spacing--30);
  color: rgba(255,255,255,.5);
}
.gr-crumb-on-dark a { color: rgba(255,255,255,.72); }
.gr-crumb-on-dark a:hover { color: #fff; }
.gr-panel-copy .gr-btn-on-dark > .wp-block-button__link {
  border-color: rgba(255,255,255,.28);
  background: transparent;
  color: #fff;
}
.gr-panel-copy .gr-btn-on-dark > .wp-block-button__link:hover { background: rgba(255,255,255,.08); }
.gr-panel-copy p { color: rgba(255,255,255,.72); max-width: 34rem; margin-inline: auto; }
.gr-panel-copy .wp-block-button__link { background: var(--wp--preset--color--paper); color: var(--wp--preset--color--ink); }

/* ============================================================
   HOMEPAGE: THE CHATTER
   Clients asking, us answering, product agents working in the margins.
   Threads start, get a reply, and clear out.
   ============================================================ */
.gr-chatter { position: absolute; inset: 0; z-index: 1; pointer-events: none; opacity: var(--chat-alpha, 0); transition: opacity .4s cubic-bezier(.32,.72,0,1); }
.gr-slot { position: absolute; left: var(--x); top: var(--y); width: 14.5rem; max-width: 20vw; display: flex; flex-direction: column; gap: .35rem; }
.gr-slot[data-side="l"] { transform: translate(0, -50%); align-items: flex-start; text-align: left; }
.gr-slot[data-side="r"] { transform: translate(-100%, -50%); align-items: flex-end; text-align: right; }
.gr-bubble {
  max-width: 100%;
  padding: .45rem .68rem;
  border-radius: 13px;
  font-size: .8125rem;
  line-height: 1.4;
  opacity: 0;
  transform: translateY(7px);
  transition: opacity .34s cubic-bezier(.32,.72,0,1), transform .34s cubic-bezier(.32,.72,0,1);
}
.gr-bubble.is-in { opacity: 1; transform: none; }
.gr-bubble.is-out { opacity: 0; transform: translateY(-5px); }
.gr-bubble[data-voice="client"] { background: rgba(255,255,255,.11); color: rgba(255,255,255,.88); }
.gr-bubble[data-voice="studio"] { background: color-mix(in oklab, var(--wp--preset--color--indigo) 62%, transparent); color: #fff; }
.gr-bubble[data-voice="agent"]  { background: rgba(255,255,255,.04); border: 1px solid rgba(255,255,255,.10); color: rgba(255,255,255,.62); }
.gr-slot[data-side="l"] .gr-bubble { border-bottom-left-radius: 4px; }
.gr-slot[data-side="r"] .gr-bubble { border-bottom-right-radius: 4px; }
.gr-who { display: flex; align-items: center; gap: .3rem; font-size: .625rem; letter-spacing: .1em; text-transform: uppercase; font-weight: 500; color: rgba(255,255,255,.4); margin-bottom: .2rem; }
.gr-slot[data-side="r"] .gr-who { flex-direction: row-reverse; }
.gr-who i { width: 5px; height: 5px; border-radius: 50%; background: var(--who, rgba(255,255,255,.4)); flex: none; }
/* the typing indicator is what makes this read as a conversation
   rather than as a set of captions */
.gr-dots { display: inline-flex; gap: 3px; align-items: center; height: 1.4em; padding: 0 .1rem; }
.gr-dots i { width: 4px; height: 4px; border-radius: 50%; background: currentColor; opacity: .3; animation: gr-blip 1.25s infinite; }
.gr-dots i:nth-child(2) { animation-delay: .16s; }
.gr-dots i:nth-child(3) { animation-delay: .32s; }
@keyframes gr-blip { 0%,62%,100% { opacity: .25; transform: translateY(0); } 30% { opacity: .95; transform: translateY(-2.5px); } }

@media (max-width: 1180px) { .gr-slot { width: 12rem; max-width: 27vw; } .gr-bubble { font-size: .7813rem; } }
@media (max-width: 760px) {
  .gr-slot:not([data-m]) { display: none; }
  /* data-side is the desktop anchor; on a phone several slots sit on the
     other side of the screen, so they re-anchor or run off the edge */
  .gr-slot[data-mside="l"] { transform: translate(0,-50%); align-items: flex-start; text-align: left; }
  .gr-slot[data-mside="r"] { transform: translate(-100%,-50%); align-items: flex-end; text-align: right; }
  .gr-slot { left: var(--mx, var(--x)); top: var(--my, var(--y)); width: 11rem; max-width: 46vw; }
  .gr-bubble { font-size: .75rem; padding: .36rem .55rem; line-height: 1.32; }
  .gr-who { margin-bottom: .1rem; }
}
@media (prefers-reduced-motion: reduce) {
  .gr-dots i { animation: none; opacity: .5; }
  .gr-bubble { transition: opacity .2s ease; transform: none !important; }
}

/* ============================================================
   HOMEPAGE: PROJECT CARDS
   Not links themselves, since each holds a button and an outbound
   link. Facts sit at the bottom so the row lines up whatever length
   the descriptions are.
   ============================================================ */
.gr-cards { display: grid; gap: var(--wp--preset--spacing--30); grid-template-columns: repeat(auto-fill, minmax(min(100%, 20rem), 1fr)); }
.gr-card {
  display: flex;
  flex-direction: column;
  padding: var(--wp--preset--spacing--50);
  border-radius: 18px;
  background: var(--tint, var(--wp--preset--color--paper-2));
}
.gr-card h3 { margin: 0; font-size: 1.3125rem; letter-spacing: -.024em; font-weight: 500; }
.gr-card p { margin-top: var(--wp--preset--spacing--20); font-size: .9688rem; line-height: 1.5; color: var(--wp--preset--color--ink-2); }
.gr-facts { margin: auto 0 0; padding-top: var(--wp--preset--spacing--50); display: grid; }
.gr-facts div { display: flex; align-items: baseline; justify-content: space-between; gap: var(--wp--preset--spacing--30); padding: .55rem 0; border-top: 1px solid rgba(22,22,26,.10); }
.gr-facts div:last-child { border-bottom: 1px solid rgba(22,22,26,.10); }
.gr-facts dt { margin: 0; font-size: .6875rem; letter-spacing: .1em; text-transform: uppercase; font-weight: 500; color: var(--wp--preset--color--ink-muted); }
.gr-facts dd { margin: 0; font-size: .875rem; text-align: right; }
.gr-facts dd a { text-decoration: underline; text-underline-offset: 2px; text-decoration-color: rgba(22,22,26,.25); }
.gr-card .wp-block-buttons { margin-top: var(--wp--preset--spacing--40); }

/* ============================================================
   HOMEPAGE: CONTACT BAND
   ============================================================ */
.gr-band-indigo { background: var(--wp--preset--color--indigo); color: #fff; }
.gr-band-indigo h2 { color: #fff; }
/* No max-width of its own. A constrained layout centres any child narrower
   than the content column, so a 36rem paragraph between a 44rem heading and a
   44rem button row sat indented from both. Matching the column width makes it
   flush, and 44rem is still a sound measure at this size. */
.gr-band-indigo p { color: rgba(255,255,255,.82); }
.gr-band-indigo .wp-block-button__link { background: var(--wp--preset--color--paper); color: var(--wp--preset--color--ink); }

/* ============================================================
   CASE PAGE
   A project page is read by someone checking whether we can
   actually build. So it alternates a column of prose with a
   column of evidence, and the evidence holds while the prose
   scrolls past it.
   ============================================================ */
.gr-case-crumb {
  display: flex;
  align-items: center;
  gap: .5rem;
  font-size: .875rem;
  color: var(--wp--preset--color--ink-muted);
  margin-top: var(--wp--preset--spacing--50);
}
.gr-case-crumb a { text-decoration: none; }
.gr-case-crumb a:hover { color: var(--wp--preset--color--ink); }

/* The title and the standfirst sit side by side. A full-bleed headline with a
   half-width paragraph tucked under its left edge leaves the right of the page
   empty and the two reading as one lopsided block. */
.gr-case-head {
  display: grid;
  grid-template-columns: minmax(0, 1.05fr) minmax(0, 1fr);
  gap: var(--wp--preset--spacing--40) var(--wp--preset--spacing--60);
  align-items: end;
  margin-top: var(--wp--preset--spacing--40);
}
.gr-case-head > * { margin: 0; }

.gr-case-lede {
  font-size: 1.1875rem;
  line-height: 1.5;
  color: var(--wp--preset--color--ink-2);
  max-width: 34rem;
}

@media (max-width: 900px) {
  /* Beside each other needs width. Below 900 they stack, and the standfirst
     goes back to following the title rather than sitting level with it. */
  .gr-case-head { grid-template-columns: 1fr; align-items: start; }
}

/* The strip under the title: the facts a buyer scans for before
   deciding whether to read the rest. */
/* A grid rather than a flex row: flex packs the five facts against the left
   edge and leaves a third of the page empty. This spreads them across it. */
.gr-case-meta {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 8rem), 1fr));
  gap: var(--wp--preset--spacing--40) var(--wp--preset--spacing--30);
  margin: var(--wp--preset--spacing--60) 0 0;
  padding: var(--wp--preset--spacing--40) 0;
  border-top: 1px solid var(--wp--preset--color--hairline);
  border-bottom: 1px solid var(--wp--preset--color--hairline);
}
.gr-case-meta div { display: flex; flex-direction: column; gap: .15rem; }
.gr-case-meta dt {
  margin: 0;
  font-size: .6875rem;
  letter-spacing: .1em;
  text-transform: uppercase;
  font-weight: 500;
  color: var(--wp--preset--color--ink-muted);
}
.gr-case-meta dd { margin: 0; font-size: .9375rem; }
.gr-case-meta dd a { text-decoration: underline; text-underline-offset: 2px; text-decoration-color: rgba(22,22,26,.25); }

/* ---- the steps ---- */
.gr-case-steps { padding: var(--wp--preset--spacing--60) 0 var(--wp--preset--spacing--70); }
.gr-case-step {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.05fr);
  gap: var(--wp--preset--spacing--60);
  align-items: start;
  padding: var(--wp--preset--spacing--70) 0;
  border-top: 1px solid var(--wp--preset--color--hairline);
}
.gr-case-step:first-child { border-top: 0; padding-top: var(--wp--preset--spacing--50); }
.gr-case-stepbody { display: grid; grid-template-columns: 2.75rem minmax(0, 1fr); gap: var(--wp--preset--spacing--30); }
.gr-case-num {
  display: grid;
  place-items: center;
  width: 2.25rem;
  height: 2.25rem;
  border-radius: 8px;
  border: 1px solid var(--wp--preset--color--hairline);
  background: var(--wp--preset--color--paper-2);
  font-size: .875rem;
  color: var(--wp--preset--color--ink-muted);
}
.gr-case-txt > * { margin-block: 0; }
.gr-case-txt > * + * { margin-top: var(--wp--preset--spacing--30); }
.gr-case-stepno {
  font-size: .6875rem;
  letter-spacing: .12em;
  text-transform: uppercase;
  font-weight: 500;
  color: var(--wp--preset--color--indigo);
  margin-top: .45rem;
}
.gr-case-txt h2 { margin-top: var(--wp--preset--spacing--20); }
.gr-case-txt p { max-width: 34rem; }

/* The evidence column holds until the next step pushes it out. Sticky only
   has travel while the column is taller than the thing stuck inside it, so
   this is worth measuring rather than assuming. */
/* min-width: 0 so a non-wrapping panel scrolls inside itself rather than
   widening the column that holds it. */
.gr-case-media { height: 100%; min-width: 0; }
.gr-case-media > * { position: sticky; top: calc(var(--gr-header-h) + var(--wp--preset--spacing--40)); margin-top: 0; }

@media (max-width: 900px) {
  /* minmax(0, 1fr), not 1fr. A bare 1fr track will not shrink below its
     content's min-content width, and the artifact panels do not wrap, so the
     column blows out to the longest line and takes the page sideways with it. */
  .gr-case-step { grid-template-columns: minmax(0, 1fr); gap: var(--wp--preset--spacing--40); padding-block: var(--wp--preset--spacing--60); }
  .gr-case-media { height: auto; }
  /* relative rather than static: the phone inset in step one is positioned
     against this, and static would let it escape to the page. */
  .gr-case-media > * { position: relative; top: auto; }
}

/* ---- what the agent produces, shown rather than described ---- */
.gr-case-artifact {
  border-radius: 14px;
  overflow: hidden;
  border: 1px solid var(--wp--preset--color--hairline);
  background: var(--wp--preset--color--deep);
}
.gr-case-artifact header {
  display: flex;
  align-items: center;
  gap: .5rem;
  padding: .65rem var(--wp--preset--spacing--40);
  background: rgba(255,255,255,.05);
  border-bottom: 1px solid rgba(255,255,255,.10);
}
.gr-case-artifact header i { width: 9px; height: 9px; border-radius: 50%; background: var(--wp--preset--color--cyan); flex: none; }
.gr-case-artifact header b { font-size: .75rem; letter-spacing: .09em; text-transform: uppercase; font-weight: 500; color: rgba(255,255,255,.62); }
/* Monospace, and not for decoration. These panels line their columns up with
   spaces, and Outfit is proportional: a capital M runs nearly four times the
   width of an i, so every column drifts out of true. */
.gr-case-artifact pre {
  margin: 0;
  padding: var(--wp--preset--spacing--40);
  color: #E8E8EE;
  font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;
  font-size: .8125rem;
  line-height: 1.6;
  white-space: pre;
  overflow-x: auto;
}

/* Where the content is genuinely tabular, a table beats aligned spaces. It
   survives a narrow column, and a screen reader can read it. */
.gr-case-artifact table {
  width: 100%;
  border-collapse: collapse;
  font-size: .8438rem;
  color: #E8E8EE;
}
.gr-case-artifact thead th {
  padding: var(--wp--preset--spacing--30) var(--wp--preset--spacing--20) .5rem;
  text-align: left;
  font-size: .625rem;
  letter-spacing: .1em;
  text-transform: uppercase;
  font-weight: 500;
  color: rgba(255,255,255,.45);
  border-bottom: 1px solid rgba(255,255,255,.12);
}
.gr-case-artifact thead th:first-child { padding-left: var(--wp--preset--spacing--40); }
.gr-case-artifact thead th:last-child { padding-right: var(--wp--preset--spacing--40); }
.gr-case-artifact tbody td {
  padding: .5rem var(--wp--preset--spacing--20);
  border-bottom: 1px solid rgba(255,255,255,.07);
  vertical-align: baseline;
}
.gr-case-artifact tbody tr:last-child td { border-bottom: 0; }
.gr-case-artifact tbody td:first-child { padding-left: var(--wp--preset--spacing--40); color: rgba(255,255,255,.72); }
.gr-case-artifact tbody td:last-child { padding-right: var(--wp--preset--spacing--40); }
.gr-case-artifact td.is-none { color: rgba(255,255,255,.32); }
.gr-case-artifact td.is-shown { color: #fff; }
.gr-case-artifact figcaption,
.gr-case-artifact .gr-case-note {
  margin: 0;
  padding: var(--wp--preset--spacing--30) var(--wp--preset--spacing--40) var(--wp--preset--spacing--40);
  font-size: .8125rem;
  line-height: 1.45;
  color: rgba(255,255,255,.55);
}
.gr-case-artifact pre b { font-weight: 500; color: #fff; }
.gr-case-artifact pre em { font-style: normal; color: rgba(255,255,255,.55); }

/* A pull quote as evidence. Used where a step turns on one sentence and a
   diagram would be padding. */
.gr-case-quote {
  margin: 0;
  padding: var(--wp--preset--spacing--50);
  border-radius: 14px;
  background: var(--wp--preset--color--paper-2);
  border: 1px solid var(--wp--preset--color--hairline);
}
.gr-case-quote p {
  margin: 0;
  font-size: 1.3125rem;
  line-height: 1.35;
  letter-spacing: -.02em;
  font-weight: 420;
  text-wrap: balance;
}
.gr-case-quote cite {
  display: block;
  margin-top: var(--wp--preset--spacing--30);
  font-style: normal;
  font-size: .6875rem;
  letter-spacing: .1em;
  text-transform: uppercase;
  font-weight: 500;
  color: var(--wp--preset--color--ink-muted);
}

/* ---- screenshots ---- */
.gr-case-media figure,
.gr-case-media .wp-block-image { margin: 0; }
.gr-case-media img { display: block; width: 100%; height: auto; border-radius: 14px; border: 1px solid var(--wp--preset--color--hairline); }
.gr-case-media figcaption {
  margin-top: var(--wp--preset--spacing--20);
  font-size: .8125rem;
  line-height: 1.45;
  color: var(--wp--preset--color--ink-muted);
}
/* The phone resting on the corner of the desktop shot. No position of its own:
   it is a direct child of the media column and so is already sticky, and a
   sticky element is a containing block for the absolute inset. Declaring
   relative here would land after that rule and quietly cancel the stick. */
.gr-case-pair { padding-bottom: 2.5rem; }
.gr-case-pair .gr-case-inset {
  position: absolute;
  right: -.5rem;
  bottom: 0;
  width: 23%;
  margin: 0;
}
.gr-case-pair .gr-case-inset img {
  border-radius: 10px;
  box-shadow: 0 12px 30px -12px rgba(22,22,26,.35);
  background: var(--wp--preset--color--paper);
}

/* ---- other projects ---- */
.gr-case-related { padding: var(--wp--preset--spacing--70) 0; }
.gr-case-rgrid {
  display: grid;
  gap: var(--wp--preset--spacing--30);
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 17rem), 1fr));
  margin-top: var(--wp--preset--spacing--50);
}
.gr-case-rgrid a {
  display: block;
  padding: var(--wp--preset--spacing--40);
  border-radius: 18px;
  background: var(--tint, var(--wp--preset--color--paper-2));
  text-decoration: none;
  transition: transform 220ms cubic-bezier(.32,.72,0,1);
}
.gr-case-rgrid a:hover { transform: translateY(-2px); }
.gr-case-rgrid b { display: block; font-size: 1.0625rem; font-weight: 500; letter-spacing: -.012em; }
.gr-case-rgrid span { display: block; margin-top: .3rem; font-size: .9063rem; color: var(--wp--preset--color--ink-2); }

@media (prefers-reduced-motion: reduce) {
  .gr-case-rgrid a:hover { transform: none !important; }
}

/* ============================================================
   LEGAL PAGES
   One column, no sidebar, no table of contents. These are read
   by someone checking a specific thing, so the headings carry
   the navigation and the facts sit in one findable block.
   ============================================================ */
.gr-doc { padding-block: var(--wp--preset--spacing--70) var(--wp--preset--spacing--60); }
.gr-doc > * { margin-block: 0; }
.gr-doc h1 {
  font-size: clamp(2.25rem, 4.5vw, 3.25rem);
  line-height: 1.06;
  letter-spacing: -.032em;
  font-weight: 700;
}
.gr-doc h2 {
  font-size: 1.3125rem;
  line-height: 1.3;
  letter-spacing: -.016em;
  font-weight: 500;
  margin-top: var(--wp--preset--spacing--60);
}
.gr-doc h3 {
  font-size: 1.0625rem;
  font-weight: 500;
  letter-spacing: -.008em;
  margin-top: var(--wp--preset--spacing--40);
}
.gr-doc p,
.gr-doc ul { margin-top: var(--wp--preset--spacing--30); }
.gr-doc ul { padding-left: 1.1rem; }
.gr-doc li { margin: .35rem 0; }
.gr-doc li::marker { color: var(--wp--preset--color--ink-muted); }
.gr-doc a { text-decoration: underline; text-underline-offset: 2px; text-decoration-color: var(--wp--preset--color--hairline); }
.gr-doc a:hover { text-decoration-color: currentColor; }

.gr-doc-effective { margin-top: var(--wp--preset--spacing--30); font-size: .9375rem; color: var(--wp--preset--color--ink-muted); }
.gr-doc-intro { margin-top: var(--wp--preset--spacing--50); font-size: 1.125rem; line-height: 1.55; color: var(--wp--preset--color--ink-2); }

/* The one place the company facts live, so they stay findable and stay true. */
.gr-doc-details { margin-top: var(--wp--preset--spacing--40); border-top: 1px solid var(--wp--preset--color--hairline); }
.gr-doc-details div {
  display: grid;
  grid-template-columns: minmax(0, 12rem) minmax(0, 1fr);
  gap: var(--wp--preset--spacing--30);
  padding: .65rem 0;
  border-bottom: 1px solid var(--wp--preset--color--hairline);
}
.gr-doc-details dt { margin: 0; font-size: .9375rem; color: var(--wp--preset--color--ink-muted); }
.gr-doc-details dd { margin: 0; }
@media (max-width: 600px) {
  .gr-doc-details div { grid-template-columns: 1fr; gap: .15rem; }
}

/* ============================================================
   THE CONTACT AGENT
   The page is the first working session. The visitor talks on
   the left, and the office writes their work order on the right
   while they watch. The panel starts as the whole window and
   draws in as the order fills: the frame closes around the work.
   ============================================================ */
.gr-focus-panel {
  width: auto;
  margin: var(--padY) var(--pad);
  height: auto;
  min-height: 74svh;
  place-items: center;
  padding: clamp(2rem, 5vw, 4rem) clamp(1.25rem, 4vw, 3.5rem);
  transition: margin 520ms cubic-bezier(.32,.72,0,1), border-radius 520ms cubic-bezier(.32,.72,0,1);
}
.gr-focus-inner { width: 100%; max-width: 66rem; }
.gr-focus-title { color: #fff; font-size: clamp(2rem, 4.5vw, 3rem); line-height: 1.05; letter-spacing: -.032em; font-weight: 700; margin: 0; text-align: center; }
.gr-focus-intro { color: rgba(255,255,255,.6); margin: var(--wp--preset--spacing--30) auto 0; max-width: 34rem; font-size: 1.0625rem; text-align: center; }

/* Three acts. Arrive: one contained chat window. During: a quiet progress
   line while the frame closes in. Done: the finished order slides in beside
   the chat as the payoff. */
.gr-intake {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--wp--preset--spacing--40);
  align-items: start;
  margin: var(--wp--preset--spacing--50) auto 0;
  max-width: 42rem;
  text-align: left;
}

/* The chat is one grounded component: messages scroll inside it, the input
   is docked to its bottom edge. */
.gr-chatwrap {
  border: 1px solid rgba(255,255,255,.12);
  background: rgba(255,255,255,.03);
  border-radius: 18px;
  padding: .9rem;
  display: flex;
  flex-direction: column;
}
.gr-status {
  margin: .4rem 0 0;
  text-align: center;
  font-size: .75rem;
  letter-spacing: .09em;
  text-transform: uppercase;
  color: rgba(255,255,255,.42);
}
.gr-status b { font-weight: 500; color: var(--wp--preset--color--cyan); }
.gr-status[hidden] { display: none; }

/* ---- the conversation ---- */
.gr-chat {
  display: flex;
  flex-direction: column;
  gap: .6rem;
  min-height: 13rem;
  max-height: min(46svh, 26rem);
  overflow-y: auto;
  padding: .15rem .15rem .5rem;
  scrollbar-width: thin;
  scrollbar-color: rgba(255,255,255,.2) transparent;
}
.gr-msg {
  max-width: 92%;
  padding: .7rem .95rem;
  border-radius: 15px;
  font-size: 1rem;
  line-height: 1.5;
  white-space: pre-wrap;
  overflow-wrap: break-word;
}
.gr-msg[data-role="agent"] {
  align-self: flex-start;
  border-bottom-left-radius: 5px;
  background: color-mix(in oklab, var(--wp--preset--color--indigo) 58%, transparent);
  color: #fff;
}
.gr-msg[data-role="visitor"] {
  align-self: flex-end;
  border-bottom-right-radius: 5px;
  background: rgba(255,255,255,.10);
  color: rgba(255,255,255,.92);
}
.gr-msg[data-role="system"] {
  align-self: center;
  background: none;
  color: rgba(255,255,255,.45);
  font-size: .875rem;
  text-align: center;
}
.gr-msg a { color: inherit; }

/* One control: the border sits on the form, the button lives inside it. */
.gr-chat-form {
  display: flex;
  align-items: center;
  gap: .4rem;
  margin-top: var(--wp--preset--spacing--30);
  padding: .4rem .4rem .4rem .6rem;
  border-radius: 16px;
  border: 1px solid rgba(255,255,255,.16);
  background: rgba(255,255,255,.05);
}
.gr-chat-form:focus-within { border-color: rgba(255,255,255,.42); }
.gr-chat-form textarea {
  flex: 1;
  min-height: 2.5rem;
  max-height: 10rem;
  padding: .55rem .4rem;
  border: 0;
  background: transparent;
  color: #fff;
  font: inherit;
  font-size: 1rem;
  resize: none;
}
.gr-chat-form textarea:focus { outline: none; }
.gr-chat-form textarea::placeholder { color: rgba(255,255,255,.35); }
.gr-chat-send {
  flex: none;
  border: 0;
  cursor: pointer;
  padding: .7rem 1.05rem;
  border-radius: 11px;
  font: inherit;
  font-size: .8125rem;
  font-weight: 500;
  letter-spacing: .085em;
  text-transform: uppercase;
  background: var(--wp--preset--color--paper);
  color: var(--wp--preset--color--ink);
}
.gr-chat-send:disabled { opacity: .45; cursor: default; }

/* Tap-able answers under the agent's question. */
.gr-chips { display: flex; flex-wrap: wrap; gap: .45rem; align-self: flex-start; max-width: 92%; }
.gr-chip {
  border: 1px solid rgba(255,255,255,.24);
  background: transparent;
  color: #fff;
  border-radius: 999px;
  padding: .5rem .9rem;
  font: inherit;
  font-size: .875rem;
  cursor: pointer;
  transition: background-color 160ms cubic-bezier(.32,.72,0,1), border-color 160ms cubic-bezier(.32,.72,0,1);
}
.gr-chip:hover { background: rgba(255,255,255,.09); border-color: rgba(255,255,255,.5); }

/* ---- the work order, writing itself ---- */
.gr-order[hidden] { display: none; }
.gr-order {
  border-radius: 16px;
  border: 1px solid rgba(255,255,255,.12);
  background: rgba(255,255,255,.04);
  overflow: hidden;
}
.gr-order header {
  display: flex;
  align-items: center;
  gap: .5rem;
  padding: .7rem 1.1rem;
  border-bottom: 1px solid rgba(255,255,255,.1);
  background: rgba(255,255,255,.04);
}
.gr-order header i { width: 9px; height: 9px; border-radius: 50%; background: var(--wp--preset--color--cyan); flex: none; }
.gr-order header b { font-size: .75rem; letter-spacing: .09em; text-transform: uppercase; font-weight: 500; color: rgba(255,255,255,.62); }
.gr-order header span { margin-left: auto; font-size: .6875rem; letter-spacing: .08em; text-transform: uppercase; color: rgba(255,255,255,.38); }
.gr-order dl { margin: 0; padding: .6rem 1.1rem .9rem; display: grid; gap: .55rem; }
.gr-order-line dt {
  margin: 0;
  font-size: .625rem;
  letter-spacing: .11em;
  text-transform: uppercase;
  font-weight: 500;
  color: rgba(255,255,255,.38);
}
.gr-order-line dd { margin: .1rem 0 0; font-size: .9375rem; line-height: 1.45; color: #fff; }
.gr-order-line[data-empty] dd { color: rgba(255,255,255,.22); }
.gr-order-line[data-field="fit"] dd { color: var(--wp--preset--color--cyan); }
.gr-order-foot[hidden] { display: none; }
.gr-order-foot {
  padding: .9rem 1.1rem 1.1rem;
  border-top: 1px solid rgba(255,255,255,.1);
  display: grid;
  gap: .6rem;
}
.gr-order-foot .wp-element-button { text-align: center; }
.gr-order-note { margin: 0; font-size: .8125rem; line-height: 1.5; color: rgba(255,255,255,.45); }
.gr-order-note a { color: rgba(255,255,255,.75); }
.gr-order-note a:hover { color: #fff; }

@media (prefers-reduced-motion: reduce) {
  .gr-focus-panel { transition: none; }
}

/* Skip link. WordPress prints its own for block themes and hides it with the
   .screen-reader-text utility, which outranks a single class selector. These
   match that specificity and load later, so they win without !important. */
.skip-link.screen-reader-text {
  position: absolute;
  left: -9999px;
  top: 0;
  z-index: 100;
  width: auto;
  height: auto;
  margin: 0;
  overflow: visible;
  clip-path: none;
  padding: .7rem 1.1rem;
  background: var(--wp--preset--color--ink);
  color: var(--wp--preset--color--paper);
  border-radius: 0 0 9px 0;
  font-size: .875rem;
  line-height: 1.3;
  text-decoration: none;
}
.skip-link.screen-reader-text:focus {
  left: 0;
  background: var(--wp--preset--color--ink);
  color: var(--wp--preset--color--paper);
  clip-path: none;
}
