/* =========================================================
   OSCAR GARAY — DASHBOARD SYSTEM (light + dark)
   Floating cards with real shadows, large radii, a saturated blue.
   Semantic tokens: every colour in this file resolves to one of these,
   and the dark theme is just another value set for the same names.

   Theme is set on <html data-theme="light|dark"> by an inline script in
   each page's <head> BEFORE first paint (stored choice, else the system
   preference), so there is no flash. The @media block below is only the
   no-JS fallback.

   Contrast (WCAG, checked by calculation):
     light  ink/bg 16.8 · ink-soft/bg 8.5 · label/bg 5.6 · accent-text/bg 4.7
     dark   ink/bg 17.6 · ink-soft/bg 10.7 · label/bg 7.0 · accent-text/bg 8.0
     white on --accent (button fill) 5.3 in both themes
   --accent is a FILL colour (buttons, dots). Text that is blue uses
   --accent-text, which is lighter in the dark theme so it stays AA.
   --signal: small indicator dots only — never a large fill, text or line.
   ========================================================= */
:root{
  color-scheme: light;

  --bg:            #F4F3EF;
  --page-bg:
    radial-gradient(900px 600px at 82% 8%, rgba(120,170,255,0.26), transparent 65%),
    radial-gradient(700px 500px at 6% 0%, rgba(255,255,255,0.85), transparent 70%),
    linear-gradient(180deg,#F4F3EF 0%,#EAEFFB 100%);
  --surface:       #FFFFFF;
  --surface-2:     #EAEFFB;
  --panel-bg:      rgba(255,255,255,0.94);
  --nav-bg:        rgba(244,243,239,0.98);   /* was .72 then .86: the nav is sticky now, so page content (blue card, chart) scrolls under it and the text needs the body to keep AA */
  /* page photo: how opaque each theme's photo layer is (see "PAGE PHOTO" below) */
  --photo-light:   0.36;       /* with the 6/5 blur (was 0.30 with 9/7); ES headline AA margin x1.11 - see CONTEXT.md */
  --photo-dark:    0;
  --photo-scale:   1;          /* DARK photo only: phones get a lower multiplier (0.65) because the 9:16 night crop is more contrasty */
  --photo-scale-light: 1;      /* LIGHT photo: same opacity on phones as on desktop (was 0.65 -> 0.234 effective; see CONTEXT.md) */
  --ink:           #0E1220;
  --ink-soft:      #3F465A;
  --label:         #4B5468;                  /* was #586178 (5.6:1): small mono labels sit straight on the page photo, need the headroom */
  --accent:        #1F5BFF;
  --accent-strong: #1748D6;
  --accent-text:   #1F5BFF;
  --accent-dim:    rgba(31,91,255,0.10);
  --accent-line:   rgba(31,91,255,0.35);
  --signal:        #B8FF3D;
  --edge:          rgba(15,23,42,0.14);
  --border:        rgba(15,23,42,0.09);
  --border-strong: rgba(15,23,42,0.20);

  /* elevation: a tight contact shadow + a blue-tinted mid + a long ambient one */
  --shadow-1:  0 1px 2px rgba(15,23,42,0.06), 0 6px 16px -6px rgba(15,23,42,0.12);
  --shadow-2:  0 1px 2px rgba(15,23,42,0.06), 0 14px 30px -10px rgba(31,91,255,0.18), 0 32px 60px -24px rgba(15,23,42,0.22);
  --shadow-3:  0 2px 4px rgba(15,23,42,0.08), 0 24px 56px -14px rgba(31,91,255,0.28), 0 48px 90px -30px rgba(15,23,42,0.30);
  --shadow-glow: 0 10px 26px -8px rgba(31,91,255,0.55);

  --font-body:     'General Sans', sans-serif;
  --font-mono:     'JetBrains Mono', monospace;

  /* spacing scale — every padding/margin/gap in this file resolves
     to one of these. Pick the nearest step, don't introduce a raw
     px value for a one-off case. */
  --space-1:   4px;
  --space-2:   8px;
  --space-3:  12px;
  --space-4:  16px;
  --space-5:  20px;
  --space-6:  24px;
  --space-7:  32px;
  --space-8:  40px;
  --space-9:  48px;
  --space-10: 64px;
  --space-11: 88px;
  --space-12: 96px;
  --space-13: 120px;
  --space-14: 150px;

  --max-w:         1240px;
  --gutter:        var(--space-7);   /* side padding of the page column; --space-5 on small screens */
  --section-pad:   var(--space-10);  /* top AND bottom padding of a section: 64 + 64 = 128 between two sections; 48 on phones */
  --gap-card:      var(--space-6);   /* 24: between the big content cards (facts, data panel, process, service blocks) */
  --gap-list:      var(--space-4);   /* 16: between compact list items (stat strip, service rows, FAQ) */
  /* Type scale for headings. ONE h1 size for both pages (hero-title and page-title), and h2 always
     clearly below it: h1/h2 >= 1.3 at every width (it was 1.0 on phones, 1.02 at 1024x768, 1.08 at
     1366x768, and the final-CTA h2 was bigger than the h1). Phones and short desktops re-set --h1-size below. */
  --h1-size:       clamp(2.3rem, 1rem + 3.8vw, 4.3rem);
  --h2-size:       clamp(1.5rem, 0.8rem + 2.2vw, 3rem);
  --radius:        18px;             /* cards */
  --radius-sm:     12px;             /* inputs, chips */
  --radius-lg:     26px;             /* hero-scale cards */
  --radius-pill:   999px;

  --ease:          cubic-bezier(.16,.84,.44,1);
}

/* dark theme: same names, other values */
:root[data-theme="dark"]{
  color-scheme: dark;

  --bg:            #070B18;
  --page-bg:
    radial-gradient(900px 600px at 82% 8%, rgba(31,91,255,0.34), transparent 65%),
    radial-gradient(700px 500px at 8% 100%, rgba(255,170,60,0.07), transparent 70%),
    linear-gradient(180deg,#070B18 0%,#0B1430 100%);
  --surface:       #0F1730;
  --surface-2:     #17224A;
  --panel-bg:      rgba(15,23,48,0.94);
  --nav-bg:        rgba(7,11,24,0.92);
  --photo-light:   0;
  --photo-dark:    0.40;
  --ink:           #EEF2FF;
  --ink-soft:      #B4BFDF;
  --label:         #A3ADD0;                  /* was #8D99C0: the lit parts of the city photo sit behind bare eyebrows on phones */
  --accent-strong: #3D74FF;
  --accent-text:   #7EA3FF;
  --accent-dim:    rgba(126,163,255,0.14);
  --accent-line:   rgba(126,163,255,0.40);
  --edge:          rgba(180,195,255,0.16);
  --border:        rgba(180,195,255,0.11);
  --border-strong: rgba(180,195,255,0.24);

  --shadow-1:  0 1px 2px rgba(0,0,0,0.4), 0 8px 20px -8px rgba(0,0,0,0.6);
  --shadow-2:  0 1px 2px rgba(0,0,0,0.5), 0 16px 34px -12px rgba(0,0,0,0.65), 0 0 0 1px rgba(126,163,255,0.06);
  --shadow-3:  0 2px 4px rgba(0,0,0,0.5), 0 28px 60px -16px rgba(0,0,0,0.75), 0 0 40px -12px rgba(31,91,255,0.35);
  --shadow-glow: 0 10px 28px -8px rgba(31,91,255,0.75);
}
/* no-JS fallback: follow the system unless a theme was set explicitly */
@media (prefers-color-scheme: dark){
  :root:not([data-theme]){
    color-scheme: dark;
    --bg:#070B18; --surface:#0F1730; --surface-2:#17224A; --panel-bg:rgba(15,23,48,0.94); --nav-bg:rgba(7,11,24,0.92);
    --page-bg:linear-gradient(180deg,#070B18 0%,#0B1430 100%);
    --photo-light:0; --photo-dark:0.40;
    --ink:#EEF2FF; --ink-soft:#B4BFDF; --label:#A3ADD0; --accent-strong:#3D74FF; --accent-text:#7EA3FF;
    --accent-dim:rgba(126,163,255,0.14); --accent-line:rgba(126,163,255,0.40);
    --edge:rgba(180,195,255,0.16); --border:rgba(180,195,255,0.11); --border-strong:rgba(180,195,255,0.24);
    --shadow-1:0 8px 20px -8px rgba(0,0,0,0.6); --shadow-2:0 16px 34px -12px rgba(0,0,0,0.65); --shadow-3:0 28px 60px -16px rgba(0,0,0,0.75); --shadow-glow:0 10px 28px -8px rgba(31,91,255,0.75);
  }
}

*,*::before,*::after{ box-sizing:border-box; }
/* overflow-x on both html and body is a hard backstop — some browsers only honor it on one or
   the other depending on quirks mode / scroll-anchoring behavior. This is a safeguard on top of
   (not instead of) actually containing runaway content, see .hero-portrait and the hero portrait
   for the real fix to the mobile scroll bug.
   `clip` (not `hidden`): hidden turns html/body into scroll containers, which silently kills
   `position:sticky` on the nav (it stuck to a container that never scrolls). clip gives the same
   horizontal clipping without creating a scroll container. The `hidden` line is only the fallback
   for browsers without `clip` (Safari < 16), where the nav simply stays non-sticky as before. */
html{ scroll-behavior:smooth; overflow-x:hidden; overflow-x:clip; }
/* ES visitors: the HTML text is English and js/main.js swaps it, so the <head> script marks
   <html> as i18n-pending and main.js (or a 2.5s timer) releases it. body > * keeps the page
   photo (a pseudo-element) visible so this is never a blank white flash. */
html.i18n-pending body > *{ visibility:hidden; }

@media (prefers-reduced-motion: reduce){
  html{ scroll-behavior:auto; }
  *,*::before,*::after{ animation-duration:0.01ms !important; animation-iteration-count:1 !important; transition-duration:0.01ms !important; }
}

body{
  margin:0;
  background-color:var(--bg);
  background-image:var(--page-bg);
  background-repeat:no-repeat;
  background-size:100% 100%;
  color:var(--ink);
  font-family:var(--font-body);
  font-size:16px;
  line-height:1.55;
  -webkit-font-smoothing:antialiased;
  overflow-x:hidden; overflow-x:clip;
}

/* =========================================================
   PAGE PHOTO — a blurred landscape (light) / night city (dark) behind the
   whole page, not just the hero.
   - The blur is baked into the files (tools/build-backgrounds.sh): the browser
     only paints a bitmap, never a live blur filter (which is what makes phones
     drop frames). 14-23 KB each.
   - Two fixed layers, one per theme, ALWAYS both present; a theme switch only
     cross-fades their opacity. Nothing is fetched or decoded at toggle time, so
     there is no flash. Opacity comes from the --photo-* tokens above.
   - z-index:-1: under every in-flow block, above the canvas colour/gradient
     (--page-bg still shows through where the photo is translucent). If an image
     fails to load the page is simply the plain --bg gradient it was before.
   - fixed + 100lvh (not background-attachment:fixed, which iOS ignores) so the
     layer does not resize/jump when the mobile URL bar collapses.
   - Phones/portrait get a 9:16 crop so `cover` does not discard 75% of a 16:9.
   ========================================================= */
body::before, body::after{
  content:""; position:fixed; top:0; left:0; width:100%;
  height:100vh; height:100lvh;
  z-index:-1; pointer-events:none;
  background-repeat:no-repeat; background-position:center; background-size:cover;
  transition:opacity .5s var(--ease);
}
body::before{ background-image:url("../assets/images/bg-light-wide.webp?v=20260921"); opacity:calc(var(--photo-light) * var(--photo-scale-light)); }
body::after { background-image:url("../assets/images/bg-dark-wide.webp?v=20260920");  opacity:calc(var(--photo-dark) * var(--photo-scale)); }
@media (max-aspect-ratio:1/1){
  :root{ --photo-scale:0.65; }
  body::before{ background-image:url("../assets/images/bg-light-tall.webp?v=20260923"); }
  body::after { background-image:url("../assets/images/bg-dark-tall.webp?v=20260920"); }
}

h1,h2,h3,h4{
  font-family:var(--font-body);
  margin:0;
  font-weight:600;
  letter-spacing:-0.02em;
}

p{ margin:0; }
a{ color:inherit; text-decoration:none; }
ul{ list-style:none; margin:0; padding:0; }
button{ font-family:inherit; cursor:pointer; }

::selection{ background:var(--accent); color:#fff; }

:focus-visible{
  outline:2px solid var(--accent);
  outline-offset:3px;
  border-radius:4px;
}

main, header, footer{ position:relative; z-index:1; }

/* =========================================================
   NAV — typographic signature, the page links, language toggle, one CTA.
   From 860px up the links sit in the row. Below 860px .nav-links becomes a
   dropdown card opened by the menu button (.menu-toggle, js/main.js), so the
   row never has to fit more than the logo + the three controls. Breakpoint
   moved 768->860 (2026-09-23) when the "Home" link made ES ("Inicio ·
   Servicios · Sobre mí") overflow the flat row from 768 to 825px even at the
   tightest reasonable gap (12px) — see the 768-860px gap rule below, kept
   even though it's no longer load-bearing at this new breakpoint. The CTA is
   hidden under 640px (the hero intake card / floating pill take over).
   ========================================================= */
.nav{
  position:sticky; top:0; z-index:50;
  backdrop-filter:blur(14px);
  -webkit-backdrop-filter:blur(14px);
  background:var(--nav-bg);
  border-bottom:1px solid var(--border);
}

.nav-inner{
  max-width:var(--max-w);
  margin:0 auto;
  --nav-pad-x:var(--space-7);   /* side padding, also where the menu panel's right edge sits (redefined wherever the padding is) */
  padding:var(--space-4) var(--nav-pad-x);
  display:flex;
  align-items:center;
  gap:var(--space-6);
}

.nav-logo{
  /* wolf icon on the left, the two text lines (name + tagline) on the right, centred against each other.
     --logo-fs is the size of the first line ("Oscar Garay."); the icon is exactly that tall. */
  --logo-fs:19px;
  display:inline-flex; flex-direction:row; align-items:center; gap:var(--space-2); margin-right:auto;
  line-height:1; flex-shrink:0; white-space:nowrap;
}
.nav-logo-words{ display:inline-flex; flex-direction:column; align-items:flex-start; gap:5px; }
.nav-logo-icon{ flex:none; display:block; height:var(--logo-fs); width:auto; aspect-ratio:1 / 1; }
/* one icon per theme, switched like the toggle's sun/moon: blue on light, white on dark */
.nav-logo-icon--dark{ display:none; }
:root[data-theme="dark"] .nav-logo-icon--light{ display:none; }
:root[data-theme="dark"] .nav-logo-icon--dark{ display:block; }
@media (prefers-color-scheme: dark){   /* no-JS fallback, same as the tokens */
  :root:not([data-theme]) .nav-logo-icon--light{ display:none; }
  :root:not([data-theme]) .nav-logo-icon--dark{ display:block; }
}
/* Desktop (>=641px, where the tagline is visible): the icon is the height of the whole two-line block, measured on the INK
   not on the boxes: its ear is level with the top of the capitals of "Oscar Garay." (2px under the line box's top edge) and its
   feet with the baseline of the tagline (32px), so 30px tall. Phones (<=640px) keep the icon at the first line's height,
   centred (the tagline is hidden there, so it is a single line and the two rules give the same result). */
@media (min-width:641px){
  .nav-logo{ align-items:flex-start; }
  .nav-logo-icon{ height:32.5px; margin-top:2px; }
}
.nav-logo-main{
  display:inline-flex; align-items:baseline;
  font-weight:600; font-size:var(--logo-fs); line-height:1; letter-spacing:-0.04em;
}
.nav-logo-tag{
  font-family:var(--font-mono); font-size:12px; letter-spacing:0.16em; color:var(--label);
}
.nav-logo-dot{ color:var(--accent-text); }

.nav-links{ display:flex; gap:var(--space-2); flex-shrink:0; }
.nav-link{
  font-size:14px; color:var(--ink-soft); white-space:nowrap;
  padding:var(--space-2) var(--space-3); border-radius:var(--radius-sm);
  transition:color .2s var(--ease);
}
.nav-link:hover{ color:var(--ink); }
.nav-link.is-active{
  color:var(--ink);
  text-decoration:underline; text-decoration-thickness:1px; text-underline-offset:6px;
}

.nav-actions{ display:flex; align-items:center; gap:var(--space-4); }

.lang-toggle{
  background:none; border:1px solid var(--border-strong); border-radius:var(--radius-pill);
  padding:var(--space-1) var(--space-3); font-family:var(--font-mono); font-size:12px;
  color:var(--ink-soft); display:flex; align-items:center; gap:var(--space-1);
}
.lang-toggle .is-active{ color:var(--accent-text); }
.lang-sep{ opacity:.4; }

.nav-cta{
  background:var(--accent); color:#fff; border-color:var(--accent);
  font-size:13px; padding:var(--space-2) var(--space-5);
  box-shadow:var(--shadow-glow);
}
.nav-cta:hover{ background:var(--accent-strong); border-color:var(--accent-strong); }

/* light/dark switch: the icon shows the ACTION (moon while light, sun while dark) */
.theme-toggle, .menu-toggle{
  width:36px; height:36px; padding:0; display:inline-flex; align-items:center; justify-content:center;
  background:none; border:1px solid var(--border-strong); border-radius:var(--radius-pill);
  color:var(--ink-soft); transition:color .2s var(--ease), border-color .2s var(--ease);
}
.theme-toggle:hover, .menu-toggle:hover{ color:var(--ink); border-color:var(--accent-text); }
.theme-toggle .i-sun{ display:none; }
.theme-toggle .i-moon{ display:block; }
:root[data-theme="dark"] .theme-toggle .i-sun{ display:block; }
:root[data-theme="dark"] .theme-toggle .i-moon{ display:none; }

/* menu button: same look as the theme button (shared rule above); only exists below 860px */
.menu-toggle{ display:none; cursor:pointer; }
.menu-toggle .i-close{ display:none; }
.menu-toggle[aria-expanded="true"] .i-bars{ display:none; }
.menu-toggle[aria-expanded="true"] .i-close{ display:block; }

/* 768-860px: dead code as of the 860px breakpoint above (.nav-links is the hidden dropdown
   everywhere in this range now, so its own gap doesn't matter) — kept because it's harmless and
   still narrows the gap between the logo and the menu/theme/CTA controls in that range. Left over
   from when this WAS the window that made the flat row fit two, then three, links. */
@media (min-width:768px) and (max-width:860px){
  .nav-inner{ gap:12px; }
  .nav-actions{ gap:var(--space-3); }
}

@media (max-width:859px){
  .menu-toggle{ display:inline-flex; }
  /* the same <nav> becomes a floating card under the bar; closed = out of layout, out of the tab order, out of sight */
  .nav-links{
    position:absolute; top:calc(100% + var(--space-2)); right:var(--nav-pad-x);
    min-width:200px; flex-direction:column; gap:var(--space-1); padding:var(--space-2);
    background:var(--surface); border:1px solid var(--border); border-radius:var(--radius);
    box-shadow:var(--shadow-3);
    opacity:0; transform:translateY(-6px); visibility:hidden; pointer-events:none;
    transition:opacity .18s var(--ease), transform .18s var(--ease), visibility 0s linear .18s;
  }
  .nav-links.is-open{
    opacity:1; transform:none; visibility:visible; pointer-events:auto;
    transition-delay:0s;
  }
  .nav-links .nav-link{ display:block; font-size:15px; padding:var(--space-3) var(--space-4); }
  .nav-links .nav-link:hover{ background:var(--accent-dim); }
}

/* =========================================================
   BUTTONS
   ========================================================= */
.btn{
  display:inline-flex; align-items:center; gap:var(--space-2);
  font-family:var(--font-body); font-weight:600; font-size:14px;
  padding:var(--space-3) var(--space-6); border-radius:var(--radius-pill);
  border:1px solid transparent;
  transition:transform .2s var(--ease), background .2s var(--ease), border-color .2s var(--ease), color .2s var(--ease);
  white-space:nowrap;
}
.btn svg{ transition:transform .2s var(--ease); }
.btn:hover svg{ transform:translateX(3px); }

.btn-primary{
  background:var(--accent); color:#fff; box-shadow:var(--shadow-glow);
}
.btn-primary:hover{ background:var(--accent-strong); transform:translateY(-1px); }

.btn-outline{
  border-color:var(--border-strong); color:var(--ink);
}
.btn-outline:hover{ border-color:var(--accent-text); color:var(--accent-text); }

.btn-lg{ padding:var(--space-4) var(--space-7); font-size:15px; }

/* =========================================================
   CARD PRIMITIVE — the unit of the whole system. A floating surface:
   large radius, hairline border, layered real shadow. Variants:
   .card--flat  no shadow (nested inside another card)
   .card--dark  the concierge card: deep blue, glowing, the ONLY dark card
   ========================================================= */
.card,
.fact, .service-row, .service-detail, .process-step, .faq-item, .footer-inner, .final-cta-inner{
  background:var(--surface);
  border:1px solid var(--border);
  border-radius:var(--radius);
  box-shadow:var(--shadow-2);
}
.card--flat{ box-shadow:none; }

/* =========================================================
   TYPO UTILITIES
   ========================================================= */
.eyebrow{
  font-family:var(--font-mono); font-size:12px; letter-spacing:0.08em;
  color:var(--label); display:flex; align-items:center; gap:var(--space-2);
  margin-bottom:var(--space-5); text-transform:uppercase;
}
.eyebrow-dot{
  width:6px; height:6px; border-radius:50%; background:var(--accent);
}
@keyframes pulse{ 0%,100%{ opacity:1; } 50%{ opacity:.35; } }

/* =========================================================
   HERO — headline, one-line pitch, and the intake card (the real
   chat, see js/main.js + window.OGChat). Portrait on the right.
   ========================================================= */
.hero{
  max-width:var(--max-w);
  margin:0 auto;
  padding:var(--space-10) var(--space-7) var(--space-11);
  min-height:calc(100vh - 68px);
  display:flex; flex-direction:column; justify-content:safe center;
}

.hero-inner{
  display:grid;
  grid-template-columns:minmax(0,1.05fr) minmax(0,0.95fr);
  grid-template-areas:"copy stage" "stats stats";
  gap:var(--space-9) var(--space-10);
  align-items:center;
}
/* min-width:0 so a wide child (the textarea row) can't push a track past its fr share. */
.hero-copy{ grid-area:copy; min-width:0; }

/* Right column: the free-standing portrait (P3) with the concierge card
   overlapping its lower-right corner, like the reference mockup. */
.hero-stage{ grid-area:stage; position:relative; min-width:0; }
.hero-portrait{
  position:relative; z-index:0; isolation:isolate;
  width:100%;
  aspect-ratio:1 / 1.12;
  max-height:min(620px, 64vh);   /* same cap the first-screen fit was validated with */
  margin-left:auto;
  /* THE containment: the strand canvas is exactly this box and is clipped to it, so
     nothing can spill onto the headline / text above. (clip, with hidden as fallback) */
  overflow:hidden; overflow:clip;
}
/* the photo (cutout, no card): anchored to the bottom, fades out at its sides and foot */
.hero-portrait-img{
  /* fills the portrait box below a 24px headroom for the strands, foot on the box bottom (the mask
     fades it there). The box is what is left above the concierge card, so the head scales with it and
     never meets the card. Centred on the column's axis, the same axis the concierge sits on (it was
     pulled right, ~80px off the column centre, with 192px empty on its left). */
  position:absolute; left:50%; transform:translateX(-50%); top:var(--space-6);
  height:calc(100% - var(--space-6)); width:auto; max-width:none; display:block;
  user-select:none; -webkit-user-drag:none; pointer-events:none;
  -webkit-mask-image:linear-gradient(to bottom,#000 var(--fade-from,58%),transparent var(--fade-to,97%)),linear-gradient(to right,transparent 0,#000 8%,#000 92%,transparent 100%);
  -webkit-mask-composite:source-in;
  mask-image:linear-gradient(to bottom,#000 var(--fade-from,58%),transparent var(--fade-to,97%)),linear-gradient(to right,transparent 0,#000 8%,#000 92%,transparent 100%);
  mask-composite:intersect;
}
/* black shirt on a dark page would vanish: a thin blue rim keeps the silhouette readable */
:root[data-theme="dark"] .hero-portrait-img{
  filter:drop-shadow(0 0 1px rgba(150,185,255,0.55)) drop-shadow(0 0 18px rgba(31,91,255,0.30));
}
.hero-portrait canvas{
  position:absolute; inset:0;
  width:100%; height:100%;
  display:block; pointer-events:none;
}
.hero-stage .intake{
  position:absolute; right:0; bottom:0; z-index:2;
  width:min(440px, 100%); max-width:none; margin-top:0;
}

.hero-title{
  font-weight:700;
  font-size:var(--h1-size);
  line-height:1.0;
  letter-spacing:-0.04em;
  color:var(--ink);
}
/* one sentence per line, so the break never lands mid-phrase (EN or ES) */
.hero-title > span{ display:block; text-wrap:balance; }
.hero-title-accent{ color:var(--accent-text); }

.hero-sub{
  margin-top:var(--space-6); max-width:46ch;
  font-size:18px; color:var(--ink-soft); line-height:1.6;
}

/* ---- intake card: hard ink border, no shadow (editorial, not "widget") ---- */
.intake{
  margin-top:var(--space-8); max-width:580px;
  background:var(--surface);
  border:1px solid var(--ink); border-radius:var(--radius);
  padding:var(--space-6);
  display:flex; flex-direction:column; gap:var(--space-3);
}
.intake-eyebrow{
  font-family:var(--font-mono); font-size:12px; letter-spacing:0.08em;
  text-transform:uppercase; color:var(--label);
}
.intake-prompt{
  font-size:clamp(1.25rem, 1.05rem + 0.8vw, 1.6rem);
  font-weight:600; line-height:1.2; letter-spacing:-0.025em;
  color:var(--ink);
}
.intake-row{ display:flex; gap:var(--space-3); align-items:stretch; margin-top:var(--space-1); }
.intake-input{
  flex:1; min-width:0; resize:none;
  font-family:var(--font-body); font-size:15px; line-height:1.5;
  color:var(--ink);
  background:var(--bg); /* --label placeholder needs >=4.5:1: fine on --bg, not on --surface-2 */
  border:1px solid var(--border-strong); border-radius:var(--radius-sm);
  padding:var(--space-3) var(--space-4);
  transition:border-color .2s var(--ease);
}
.intake-input::placeholder{ color:var(--label); }
.intake-input:focus{ border-color:var(--ink); }
/* main call to action: --accent like every other primary button (white on
   accent 5.4:1). --signal is NOT used for large fills. */
.intake-btn{
  flex:none; display:inline-flex; align-items:center; justify-content:center; gap:var(--space-2);
  padding:0 var(--space-5);
  font-family:var(--font-body); font-weight:600; font-size:14px;
  color:#fff; background:var(--accent);
  border:1px solid var(--accent); border-radius:var(--radius-sm);
  transition:background .2s var(--ease), border-color .2s var(--ease), color .2s var(--ease);
}
.intake-btn svg{ transition:transform .2s var(--ease); }
.intake-btn:hover{ background:var(--ink); border-color:var(--ink); color:var(--bg); }
.intake-btn:hover svg{ transform:translateX(3px); }
/* one sentence (assistant notice + proof it is a real build) with the email link running on after it.
   Body font, not mono: a full sentence in mono is ~20% wider and would take a third row. */
.intake-foot{
  font-family:var(--font-body); font-size:12px; line-height:1.45;   /* was 10-11px mono */
  color:var(--label);
}
.intake-foot a{ color:var(--ink-soft); text-decoration:underline; text-underline-offset:3px;
  /* touch target: the link is 16px tall; padding grows the hit area to ~44px and the negative margin gives the
     layout back, so nothing moves */
  display:inline-block; padding:14px 8px; margin:-14px -8px; }
.intake-foot a:hover{ color:var(--accent); }

/* mono tech labels (services page tags) */
.tag{
  font-family:var(--font-mono); font-size:12px; letter-spacing:.04em;
  color:var(--label); white-space:nowrap;
}

/* ---- service chips under the pitch ---- */
/* the guarantees line: only where the stat strip is pushed below the first screen (<=900px) */
.hero-assure{ display:none; }
.hero-chips{ display:flex; flex-wrap:wrap; gap:var(--space-2) var(--space-3); margin-top:var(--space-6); }
.chip{
  display:inline-flex; align-items:center; gap:var(--space-2);
  padding:var(--space-2) var(--space-4);
  font-size:13px; font-weight:500; color:var(--ink-soft); line-height:1.2;
  background:var(--surface); border:1px solid var(--border); border-radius:var(--radius-pill);
  box-shadow:var(--shadow-1);
}
.chip svg{ flex:none; color:var(--accent-text); }
/* hero chips are links to /services#<service-key>; reset anchor defaults and
   add the same hover treatment as .btn-outline (border + text -> accent). The
   Workshop marquee below reuses .chip too but stays a plain <li>, undecorated
   and non-interactive by design — this rule only reaches the hero's <a>. */
.hero-chips a.chip{
  text-decoration:none; cursor:pointer;
  transition:border-color .2s var(--ease), color .2s var(--ease);
}
.hero-chips a.chip:hover, .hero-chips a.chip:focus-visible{
  border-color:var(--accent-text); color:var(--accent-text);
}

/* ---- "at a glance" strip: five small floating cards ---- */
.hero-stats{
  grid-area:stats;
  list-style:none; margin:0; padding:0;
  display:grid; grid-template-columns:repeat(5, minmax(0,1fr)); gap:var(--space-4);
}
.stat{
  /* Every card centres its content the same way. Left-aligned, the cards LOOK uneven even
     though the padding is identical: "4" leaves ~190px empty on its right, "Reply in <24h"
     ~45px. Centred, the inner space is symmetric whatever the text width. Value and label
     start at the same height in all five (top-aligned, same gap). */
  display:flex; flex-direction:column; align-items:center; justify-content:flex-start;
  text-align:center; gap:var(--space-1);
  /* wide and low: the vertical padding is well under the horizontal, so the content is packed
     tightly top to bottom and has room to breathe left and right (was 20/20, cards ~2.1:1) */
  padding:var(--space-3) var(--space-5);
  background:var(--surface); border:1px solid var(--border); border-radius:var(--radius);
  box-shadow:var(--shadow-1);
}
.stat{ container-type:inline-size; }   /* the value sizes itself to THIS card's width (cqi), not the viewport's */
.stat-value{
  font-weight:700; font-size:clamp(1.1rem, 0.8rem + 0.8vw, 1.5rem);
  line-height:1.1; letter-spacing:-0.03em; color:var(--ink);
  white-space:nowrap;   /* one line always: a value that wrapped pushed its label 29px below the other four */
}
/* Fit the LONGEST value of each language in its card, with a little slack (measured: EN "Reply in <24h"
   needs 5.95em, ES "Respuesta en <24 h" 8.75em, so 15cqi / 10.8cqi = 89% / 95% of the card). Browsers
   without container units keep the clamp() above. */
.stat-value{ font-size:min(clamp(1.1rem, 0.8rem + 0.8vw, 1.5rem), 15cqi); }
[data-lang="es"] .stat-value{ font-size:min(clamp(1.1rem, 0.8rem + 0.8vw, 1.5rem), 10.8cqi); }
.stat-label{
  font-family:var(--font-mono); font-size:12px; line-height:1.35; letter-spacing:0.04em;   /* was 10px: these carry the guarantees */
  text-transform:uppercase; color:var(--label);
  text-wrap:balance;   /* two-line labels split evenly instead of leaving a one-word second line */
}

/* ---- the concierge card: deep blue, glowing — the ONLY dark card on the site,
   in both themes. Skin only (layout lives in the .intake rules above). ---- */
.intake{
  background:linear-gradient(155deg,#1E47C9 0%,#12296F 48%,#0A1440 100%);
  border:1px solid rgba(255,255,255,0.16);
  border-radius:var(--radius-lg);
  box-shadow:inset 0 1px 0 rgba(255,255,255,0.20), 0 0 0 1px rgba(31,91,255,0.25), 0 20px 54px -14px rgba(31,91,255,0.60), 0 44px 90px -34px rgba(10,20,64,0.70);
  color:#fff;
}
.intake-eyebrow{ color:rgba(255,255,255,0.74); }
.intake-prompt{ color:#fff; }
.intake-input{
  background:rgba(6,12,40,0.55); color:#fff;
  border:1px solid rgba(255,255,255,0.24); border-radius:var(--radius-sm);
}
.intake-input::placeholder{ color:rgba(255,255,255,0.66); }
.intake-input:focus{ border-color:#fff; }
.intake-btn{
  background:#fff; color:#1F5BFF; border:1px solid #fff; border-radius:var(--radius-pill);
  padding:0 var(--space-6);
}
.intake-btn:hover{ background:#E6EDFF; border-color:#E6EDFF; color:#1748D6; }
.intake-foot{ color:rgba(255,255,255,0.80); }
.intake-foot a{ color:#fff; }
.intake-foot a:hover{ color:#CFE0FF; }

/* ---- desktop: the concierge is a MODERATELY smaller card (now the full width of the column, 528px, with tighter padding,
   prompt and controls; not a corner bubble) placed at the portrait's FOOT, and it stays the biggest
   panel of the column and the main CTA. The column is a fixed-height flex stack: the card takes its
   natural height (EN and ES differ) and the portrait takes what is left, so the head can never run
   into the card whatever the language or screen height (before, the card had a fixed size on top of
   a portrait box that shrank with the viewport, and covered the chin at 1366x768 and below).
   --chest: how far the card overlaps the portrait's foot. --stage-hang: how far it hangs into the row
   gap below; the gap under the column keeps a clear 24px (row gap 48 - hang 24; the short-screen rule
   pairs 40 with 16). ---- */
.hero-stage{ --stage-h:min(620px, 64vh); --stage-hang:var(--space-6); --chest:var(--space-8); }
@media (min-width:901px){
  .hero-stage{ display:flex; flex-direction:column; height:var(--stage-h); }
  .hero-portrait{ flex:1 1 0; min-height:0; aspect-ratio:auto; max-height:none; margin:0; }
  .hero-stage .intake{
    position:relative; right:auto; bottom:auto; flex:none; align-self:center;   /* same axis as the portrait */
    width:100%; padding:var(--space-5);
    margin-top:calc(-1 * var(--chest)); margin-bottom:calc(-1 * var(--stage-hang));
  }
  /* The photo's bottom fade is exactly the band the card covers: opaque down to the card's top edge,
     fully faded by the time it goes under it, so no blurred smear is left showing between the head
     and the card. (The card is wider than the figure, so the band is hidden end to end.) */
  .hero-portrait-img{ --fade-from:calc(100% - var(--chest)); --fade-to:100%; }
  .hero-stage .intake-prompt{ font-size:clamp(1.15rem, 0.95rem + 0.55vw, 1.4rem); }
  /* tighter controls so the placeholder still fits in the narrower card */
  .hero-stage .intake-input{ font-size:14px; padding:var(--space-3); }
  .hero-stage .intake-btn{ padding:0 var(--space-4); }
}
/* the ES placeholder is ~20% longer: on the narrower card (<= ~1090px) it needs a third line;
   from ~1100px the card is wide enough for two */
@media (min-width:901px) and (max-width:1090px){
  [data-lang="es"] .hero-stage .intake-input{ min-height:calc(3 * 1.5em + 2 * var(--space-3) + 2px); }
}

/* =========================================================
   FACTS — three plain statements, hairline rules, no boxes
   ========================================================= */
.facts{ }
.facts-inner{
  max-width:var(--max-w); margin:0 auto; padding:var(--section-pad) var(--gutter);
  display:grid; grid-template-columns:repeat(3,1fr); gap:var(--gap-card);
}
.fact{ display:flex; flex-direction:column; gap:var(--space-3); padding:var(--space-6); }
.fact-index{
  font-family:var(--font-mono); font-size:12px; color:var(--label);
}
.fact-text{ font-size:15.5px; color:var(--ink-soft); line-height:1.6; max-width:38ch; }

/* =========================================================
   DATA PANEL (P4) — commit activity (wide) + stack + location. Cards from the
   system's own primitive. The bars are plain boxes sized by a 0..1 --h; a week
   with no commits is a thin tick, not a gap, so an empty week reads as "0".
   ========================================================= */
/* top is 40, not 64: the hero above already carries 88 below its strip, so 88 + 40 = the same 128 as every other section boundary */
.panel{ max-width:var(--max-w); margin:0 auto; padding:var(--space-8) var(--gutter) var(--section-pad); }
.panel .section-head{ margin-bottom:var(--space-7); }
.panel-grid{
  display:grid; grid-template-columns:minmax(0,1.7fr) minmax(0,1fr); gap:var(--gap-card); align-items:stretch;
}
.panel-side{ display:grid; grid-template-rows:1fr auto; gap:var(--gap-card); min-width:0; }
.panel-card{ padding:var(--space-6); display:flex; flex-direction:column; gap:var(--space-4); min-width:0; }
.panel-head{ display:flex; flex-direction:column; gap:var(--space-1); }
.panel-label{
  font-family:var(--font-mono); font-size:12px; letter-spacing:0.08em; text-transform:uppercase; color:var(--label);
}
.panel-sub{ font-size:14px; line-height:1.5; color:var(--ink-soft); }
.panel-figure{
  font-size:clamp(1.25rem, 1rem + 0.9vw, 1.75rem); font-weight:600; letter-spacing:-0.03em; line-height:1.15; color:var(--ink);
}
.panel-foot{ font-size:12px; line-height:1.5; color:var(--label); margin-top:auto; }
.panel-activity.is-empty .panel-foot{ display:none; }

.chart{ flex:1; display:flex; align-items:flex-end; min-width:0; }   /* spare card height goes ABOVE the bars, not under the axis */
.chart > *{ flex:1; min-width:0; }
.chart[hidden]{ display:none; }
.chart-cols{
  list-style:none; margin:0; padding:0;
  display:grid; grid-template-columns:repeat(auto-fit, minmax(0,1fr)); grid-auto-flow:column; gap:var(--space-2);
  align-items:end;
}
.chart-col{
  display:flex; flex-direction:column; align-items:center; justify-content:flex-end; height:172px;
}
.chart-n{
  font-family:var(--font-mono); font-size:12px; line-height:16px; height:16px; color:var(--ink-soft);
}
.chart-bar{
  display:block; width:100%; max-width:36px;
  height:max(3px, calc(var(--h, 0) * 120px));
  background:var(--accent); border-radius:6px 6px 2px 2px;
}
.chart-col.is-zero .chart-bar{ background:var(--border-strong); border-radius:2px; }
.chart-x{
  font-family:var(--font-mono); font-size:12px; line-height:16px; height:16px; margin-top:var(--space-1);
  color:var(--label); text-transform:uppercase; letter-spacing:0.04em; white-space:nowrap;
}

.stack-chips{ display:flex; flex-wrap:wrap; gap:var(--space-2); margin:0; padding:0; list-style:none; }
.stack-chips .chip{ padding:var(--space-1) var(--space-3); font-size:12.5px; box-shadow:none; transition:border-color .2s var(--ease); }
/* decorative only — no link, no cursor change, just a subtle acknowledgement of the hover */
.stack-chips .chip:hover{ border-color:var(--accent-text); }
.panel-place{
  display:flex; align-items:center; gap:var(--space-2);
  font-size:clamp(1.15rem, 0.95rem + 0.7vw, 1.5rem); font-weight:600; letter-spacing:-0.025em; color:var(--ink);
}
.panel-place svg{ flex:none; color:var(--accent-text); }

/* =========================================================
   SERVICES TEASER — numbered rows split by hairlines (price in mono,
   right-aligned). Not interactive, so no hover state on purpose.
   ========================================================= */
.services-teaser{
  max-width:var(--max-w); margin:0 auto; padding:var(--section-pad) var(--gutter);
}
.section-head{ max-width:760px; margin-bottom:var(--space-9); }
.section-title{
  font-size:var(--h2-size); line-height:1.05; letter-spacing:-0.035em;
  text-wrap:balance;
}

.services-list{ display:flex; flex-direction:column; gap:var(--gap-list); }
.service-row{
  display:grid;
  grid-template-columns:64px minmax(0,1.1fr) minmax(0,1.5fr) 132px; /* fixed price column: an auto one shifts the fr tracks row to row */
  gap:var(--space-6);
  align-items:baseline;
  padding:var(--space-7) var(--space-7);
}
.service-num{
  font-family:var(--font-mono); font-size:12px; color:var(--label);
}
.service-price{
  font-family:var(--font-mono); font-size:13px; color:var(--ink); white-space:nowrap; text-align:right;
}
.service-row h3{
  font-size:clamp(1.25rem, 1rem + 0.9vw, 1.75rem); font-weight:600; line-height:1.15; letter-spacing:-0.03em;
}
.service-row p{
  font-size:15px; color:var(--ink-soft); line-height:1.6; max-width:52ch;
}

.services-teaser-cta{
  margin-top:var(--space-8); display:flex; justify-content:flex-start;
}

/* =========================================================
   FINAL CTA — a card like every other block (it was a full-bleed white slab that broke the
   system); left-aligned text, the button opens the chat. The card look comes from the .card
   primitive list above; the section only carries the column width and the rhythm
   (--section-pad above = the same 128 as every section boundary, 24 below to the footer card).
   ========================================================= */
.final-cta{
  max-width:var(--max-w); margin:0 auto; padding:var(--section-pad) var(--gutter) 0;
}
.final-cta-inner{
  padding:var(--space-10) var(--space-9);
  display:flex; flex-direction:column; align-items:flex-start;
}
/* desktop: text on the left, the button on the right and vertically centred - a compact card, not a tall one
   with an empty right half. Below 901px it stays a single stacked column. */
@media (min-width:901px){
  .final-cta-inner{
    display:grid; grid-template-columns:minmax(0,1fr) auto; column-gap:var(--space-10); align-items:center;
    grid-template-areas:"eyebrow btn" "title btn" "sub btn";
  }
  .final-cta-inner .eyebrow{ grid-area:eyebrow; }
  .final-cta-inner h2{ grid-area:title; }
  .final-cta-inner .final-cta-sub{ grid-area:sub; margin-bottom:0; }
  .final-cta-inner .btn{ grid-area:btn; }
}
.final-cta-inner h2{
  font-size:var(--h2-size);   /* same as every section h2: it must never outrank the page h1 */
  line-height:1.02; letter-spacing:-0.04em;
  max-width:18ch; text-wrap:balance;
  margin-bottom:var(--space-5);
}
.final-cta-sub{
  color:var(--ink-soft); font-size:17px; max-width:44ch; margin-bottom:var(--space-7);
}

/* =========================================================
   PAGE HEADER (services / other inner pages)
   ========================================================= */
.page-header{
  max-width:var(--max-w); margin:0 auto;
  padding:var(--space-12) var(--space-7) var(--space-10);
}
.page-header-inner{ max-width:920px; }
.page-header-inner > .btn{ margin-top:var(--space-6); }
.page-title{
  font-size:var(--h1-size); line-height:1.02; letter-spacing:-0.04em;
  text-wrap:balance;
  color:var(--ink); margin-bottom:var(--space-6);
}
/* one sentence per line, so the break never lands mid-phrase (EN or ES) */
.page-title > span{ display:block; text-wrap:balance; }
.page-sub{
  font-size:18px; color:var(--ink-soft); line-height:1.6; max-width:52ch;
}

/* =========================================================
   SERVICES DETAIL — one hairline-ruled block per service, price /
   timeline / tags in a right-hand column. No cards.
   ========================================================= */
.services-detail{
  max-width:var(--max-w); margin:0 auto; padding:0 var(--gutter) var(--section-pad);
  display:flex; flex-direction:column; gap:var(--gap-card);
}
.service-detail{
  display:grid; grid-template-columns:minmax(0,1fr) 240px; gap:var(--space-8);
  padding:var(--space-8);
  scroll-margin-top:96px;   /* fixed nav is ~81px desktop / ~61px mobile; clears both with room to spare */
}

.service-detail-head{
  display:flex; align-items:baseline; gap:var(--space-4); margin-bottom:var(--space-5);
}
.service-detail-head h2{
  font-size:clamp(1.25rem, 1rem + 1.1vw, 2rem); font-weight:600; line-height:1.1; letter-spacing:-0.03em;   /* a step under the section h2 (it tied at 390px) */
}
.service-detail-desc{
  font-size:16px; color:var(--ink-soft); line-height:1.65; margin-bottom:var(--space-6); max-width:60ch;
}
.service-detail-list{
  display:flex; flex-direction:column; gap:var(--space-3);
}
.service-detail-list li{
  position:relative; padding-left:var(--space-7);
  font-size:14.5px; color:var(--ink-soft); line-height:1.55;
}
/* short ink dash instead of a bullet */
.service-detail-list li::before{
  content:"";
  position:absolute; left:0; top:0.8em;
  width:16px; height:1px; background:var(--ink);
}

.service-detail-meta{
  border-left:1px solid var(--edge);
  padding-left:var(--space-7);
  display:flex; flex-direction:column; gap:var(--space-5);
}
.meta-row{ display:flex; flex-direction:column; gap:var(--space-1); }
.meta-label{
  font-family:var(--font-mono); font-size:12px; letter-spacing:.08em; color:var(--label);
}
.meta-value{ font-family:var(--font-body); font-size:17px; font-weight:600; color:var(--ink); }
.meta-value.price{ font-family:var(--font-mono); font-size:16px; font-weight:500; }
.meta-tags{ display:flex; flex-wrap:wrap; gap:var(--space-2); }
.meta-tags .tag{
  padding:2px var(--space-2);
  border:1px solid var(--edge); border-radius:var(--radius-sm);
}

/* =========================================================
   ABOUT — intro, three achievement cards + the wide "freelance roots" card
   (which embeds the live Workshop activity card), credentials, timeline.
   Cards are the system's own primitive (.card). Icons are inline SVG, 24-unit grid,
   1.7 stroke, currentColor — the same spec as the nav icons — inside a tinted tile.
   Hover lift uses the `translate` property, not `transform`, so it is not undone by the
   inline transform GSAP leaves on a revealed element.
   ========================================================= */
.about-intro{ display:flex; flex-direction:column; gap:var(--space-5); }
.about-intro .page-sub{ max-width:64ch; font-size:17.5px; }

.about-cards{
  max-width:var(--max-w); margin:0 auto; padding:0 var(--gutter) var(--section-pad);
  display:flex; flex-direction:column; gap:var(--gap-card);
}
.about-grid{ display:grid; grid-template-columns:repeat(3,minmax(0,1fr)); gap:var(--gap-card); }
.about-card{
  display:flex; flex-direction:column; gap:var(--space-3); padding:var(--space-7);
  transition:translate .28s var(--ease), box-shadow .28s var(--ease), border-color .28s var(--ease);
}
.about-card-title{ font-size:20px; font-weight:600; letter-spacing:-0.02em; line-height:1.2; }
.about-card p{ font-size:15.5px; color:var(--ink-soft); line-height:1.65; }
.about-icon{
  width:48px; height:48px; display:grid; place-items:center; margin-bottom:var(--space-2);
  border-radius:var(--radius-sm); background:var(--accent-dim); color:var(--accent-text);
  transition:background .28s var(--ease), color .28s var(--ease), scale .28s var(--ease);
}
.about-icon svg{ width:26px; height:26px; display:block; }
.about-card--wide{ padding:var(--space-8); }
.about-card--wide > p{ max-width:72ch; }
.about-panel{ margin-top:var(--space-4); max-width:760px; }
@media (hover:hover){
  .about-card:hover{ translate:0 -4px; box-shadow:var(--shadow-3); border-color:var(--accent-line); }
  .about-card:hover .about-icon{ background:var(--accent); color:#fff; scale:1.06; }
}

.about-creds{ max-width:var(--max-w); margin:0 auto; padding:0 var(--gutter) var(--section-pad); }
.about-creds-inner{
  border-top:1px solid var(--border); padding-top:var(--space-8);
  display:grid; grid-template-columns:minmax(0,220px) minmax(0,1fr); gap:var(--space-4) var(--space-8);
}
.about-creds .eyebrow{ margin-bottom:0; padding-top:4px; align-self:start; }
.about-cred-list{ list-style:none; margin:0; padding:0; display:flex; flex-direction:column; gap:var(--space-3); }
.about-cred-list li{ font-size:17px; line-height:1.5; color:var(--ink); }

.about-timeline{ max-width:var(--max-w); margin:0 auto; padding:0 var(--gutter) var(--section-pad); }
.about-timeline .section-head{ margin-bottom:var(--space-8); }
.tl{
  --tl-year:88px; --tl-rail:28px;
  list-style:none; margin:0; padding:0; position:relative; max-width:880px;
  display:flex; flex-direction:column; gap:var(--space-8);
}
.tl::before{
  content:""; position:absolute; top:10px; bottom:10px; width:1px; background:var(--border-strong);
  left:calc(var(--tl-year) + var(--tl-rail) / 2);
}
.tl-item{ display:grid; grid-template-columns:var(--tl-year) var(--tl-rail) minmax(0,1fr); align-items:start; }
.tl-year{ font-family:var(--font-mono); font-size:14px; letter-spacing:0.04em; color:var(--accent-text); padding-top:2px; }
.tl-dot{
  position:relative; z-index:1; width:12px; height:12px; margin:5px auto 0; border-radius:50%;
  background:var(--surface); border:2px solid var(--accent);
  transition:scale .25s var(--ease), background .25s var(--ease);
}
.tl-item:last-child .tl-dot{ background:var(--accent); }
.tl-role{ font-size:18px; font-weight:600; letter-spacing:-0.02em; line-height:1.3; color:var(--ink); }
.tl-org{ font-size:15px; line-height:1.55; color:var(--ink-soft); margin-top:var(--space-1); }
@media (hover:hover){
  .tl-item:hover .tl-dot{ scale:1.3; background:var(--accent); }
}
@media (prefers-reduced-motion: reduce){
  .about-card:hover, .about-card:hover .about-icon, .tl-item:hover .tl-dot{ translate:none; scale:none; }
}

@media (max-width:980px){
  .about-grid{ grid-template-columns:1fr; }
  .about-creds-inner{ grid-template-columns:1fr; }
}
@media (max-width:640px){
  .about-card, .about-card--wide{ padding:var(--space-6); }
  .tl{ --tl-year:56px; --tl-rail:24px; gap:var(--space-7); }
  .tl-year{ font-size:13px; }
}

/* =========================================================
   PROCESS
   ========================================================= */
.process{
  /* width (not padding) carries the gutter, so this section's top rule has
     the same length as the service rules above it */
  width:min(calc(100% - 2 * var(--gutter)), calc(var(--max-w) - 2 * var(--gutter)));
  margin:0 auto; padding:var(--section-pad) 0;
}
.process-grid{
  display:grid; grid-template-columns:repeat(4,1fr); gap:var(--gap-card);
}
.process-step{
  display:flex; flex-direction:column; gap:var(--space-2);
  padding:var(--space-6);
}
.process-num{
  font-family:var(--font-mono); font-size:13px; color:var(--label);
}
.process-step h3{ font-size:18px; font-weight:600; letter-spacing:-0.02em; }
.process-step p{ font-size:14.5px; color:var(--ink-soft); line-height:1.6; }

/* =========================================================
   FAQ — hairline rows, same left edge as every other section
   ========================================================= */
.faq{
  width:min(calc(100% - 2 * var(--gutter)), calc(var(--max-w) - 2 * var(--gutter)));
  margin:0 auto; padding:var(--section-pad) 0;
}
.faq-list{ max-width:820px; display:flex; flex-direction:column; gap:var(--gap-list); }
.faq-item{
  padding:var(--space-5) var(--space-6);
}
.faq-item summary{
  font-family:var(--font-body); font-size:17px; font-weight:600; letter-spacing:-0.015em; color:var(--ink);
  cursor:pointer; list-style:none; display:flex; align-items:center; justify-content:space-between;
  gap:var(--space-4);
}
.faq-item summary::-webkit-details-marker{ display:none; }
.faq-item summary::after{
  content:"+";
  font-family:var(--font-mono); font-size:20px; color:var(--accent-text); flex-shrink:0;
  transition:transform .2s var(--ease);
}
.faq-item[open] summary::after{ transform:rotate(45deg); }
.faq-item p{
  font-size:15px; color:var(--ink-soft); line-height:1.65;
  margin-top:var(--space-3); max-width:62ch;
}

/* =========================================================
   FOOTER
   ========================================================= */
.footer{
  /* transparent frame: the footer is a floating card (base .card look) like every other block.
     The bottom padding is the launcher's footprint (44px pill + 20px offset) plus 16px of air,
     so at the end of the page the pill sits BELOW the card instead of covering its links. */
  padding:var(--gap-card) var(--gutter) 80px;
}
.footer-inner{
  max-width:calc(var(--max-w) - 2 * var(--space-7)); margin:0 auto;
  padding:var(--space-5) var(--space-6);
  display:flex; align-items:center; justify-content:space-between;
  flex-wrap:wrap; gap:var(--space-4);
}
.footer-left{
  display:flex; align-items:center; gap:var(--space-3);
  font-size:13px; color:var(--label);
}
.footer-links{ display:flex; gap:var(--space-6); }
.footer-links a{
  font-size:13px; color:var(--ink-soft);
  transition:color .2s var(--ease);
}
.footer-links a:hover{ color:var(--accent-text); }

/* =========================================================
   RESPONSIVE
   ========================================================= */
@media (max-width:980px){
  .service-row{ grid-template-columns:48px minmax(0,1fr) 120px; row-gap:var(--space-3); }
  .service-row .service-price{ grid-column:3; grid-row:1; }
  .service-row p{ grid-column:2 / -1; grid-row:2; }
  .facts-inner{ grid-template-columns:1fr; }
  .panel-grid{ grid-template-columns:1fr; }
  .panel-side{ grid-template-rows:auto; }
  .service-detail{ grid-template-columns:1fr; }
  .service-detail{ gap:var(--space-6); }
  .service-detail-meta{ border-left:none; border-top:1px solid var(--border); padding-left:0; padding-top:var(--space-6); }
  .process-grid{ grid-template-columns:repeat(2,1fr); }
}

/* Short desktop screens (1366x768, 1280x720): tighten the vertical rhythm so the
   whole 'at a glance' strip still fits in the first screen without scrolling. */
@media (min-width:901px) and (max-height:820px){
  .hero{ padding-top:var(--space-6); padding-bottom:var(--space-8); }
  /* Short screens: the ES card is ~277px tall on a ~430px column, which left the head ~90px wide.
     Give the column back some of the spare height (the strip still ends >=20px above the fold),
     overlap the portrait's foot a little more and compact the card. */
  .hero-stage{ --stage-h:min(620px, 60vh); --stage-hang:var(--space-4); --chest:calc(var(--space-8) + var(--space-4)); }
  .hero-stage .intake{ padding:var(--space-4) var(--space-5); }
  .hero-stage .intake-prompt{ font-size:1.2rem; }
  .hero-inner{ row-gap:var(--space-8); }   /* 24px clear under the hanging concierge (40 - 16) */
  :root{ --h1-size:clamp(2.1rem, 1rem + 3vw, 3.5rem); }   /* short desktop: keeps the strip above the fold */
  .hero-sub{ margin-top:var(--space-4); font-size:17px; }
  .hero-chips{ margin-top:var(--space-4); }
  .stat{ padding:var(--space-2) var(--space-5); }
}

/* Tablet and below: one column, explicit order. The wrappers become
   display:contents so their children can be ordered against each other:
   pitch -> numbers -> concierge card (the CTA) -> chips -> portrait. */
@media (max-width:900px){
  /* stretch, not the desktop's center: each item must take the full column width
     (otherwise the strip shrinks to its content and is cut off on both sides) */
  .hero-inner{ display:flex; flex-direction:column; align-items:stretch; gap:var(--hero-gap); --hero-gap:var(--space-6);
    /* --m-img = height of the WHOLE photo on phones; --m-lap (how far the card overlaps its foot) is a fraction of it.
       Both are shared by the photo (fade) and the card (overlap): siblings, so they live on their parent. */
    --m-img:clamp(179px, 45.8vw, 300px);   /* 179px on phones (<=390px wide); scales up on tablets. Was 190 / 48.7vw: 11px given back for the guarantees line */ --m-lap:calc(var(--m-img) * 0.103); }
  .hero-copy, .hero-stage{ display:contents; }
  .hero-copy > .eyebrow{ order:1; margin-bottom:0; }
  .hero-title{ order:2; }
  .hero-sub{ order:3; margin-top:0; }
  .hero-assure{
    /* tucked right under the sub and close to the portrait: the line costs ~12px of height, which the
       portrait gives back below (--m-img), so the concierge input stays exactly where it was */
    display:block; order:3; margin:calc(-1 * var(--hero-gap) + var(--space-1)) 0 calc(-1 * var(--space-2));
    font-size:13px; font-weight:600; line-height:1.2; letter-spacing:0.01em; color:var(--ink);
  }
  /* Phone/tablet order: pitch -> PORTRAIT -> concierge -> numbers -> chips.
     The photo keeps the SAME FRAMING as desktop, only scaled: the whole cutout is visible, 6.2% of its
     height of headroom on top, and the card overlaps its foot by 10.3% (chin -> card edge = 36% of the photo
     height: neck, shoulders and shirt, as on desktop). An earlier phone crop cut the photo at 70% of its
     height and left 4% between chin and card; that read as cut off at the neck. The photo's bottom fade
     lives entirely inside the overlap band, so no blurred edge shows between the head and the card. */
  .hero-portrait{
    order:4; width:100%; max-width:420px; margin:0 auto;
    aspect-ratio:auto; height:calc(var(--m-img) * 1.062); max-height:none;
    z-index:auto; isolation:auto;
  }
  .hero-portrait-img{
    top:calc(var(--m-img) * 0.062); height:var(--m-img);
    --fade-from:calc(100% - var(--m-lap)); --fade-to:100%;
  }
  /* Paint order = the flex order, because all four are positioned with z-index:auto: the card paints over the
     photo's foot, and its glow is painted UNDER the numbers/chips that follow (a z-index on the card would
     have put the glow OVER them; a flex item honours z-index even when static). */
  .hero-stage .intake{ order:5; position:relative; z-index:auto; width:auto; margin-top:calc(-1 * (var(--m-lap) + var(--hero-gap))); }
  .hero-stats{ order:6; position:relative; }
  .hero-chips{ order:7; margin-top:0; position:relative; }

  /* the strip becomes a swipeable row (edge to edge) so five cards do not
     push the call to action out of the first screen */
  .hero-stats{
    display:flex; overflow-x:auto; scroll-snap-type:x mandatory; -webkit-overflow-scrolling:touch;
    gap:var(--gap-list);
    margin:0 calc(-1 * var(--gutter)); padding:var(--space-2) var(--gutter) var(--space-3);
    scroll-padding-inline:var(--gutter);   /* snap to the padded edge, not flush to the screen */
    scrollbar-width:none;
  }
  .hero-stats::-webkit-scrollbar{ display:none; }
  .stat{ flex:0 0 min(46vw, 200px); scroll-snap-align:start; }
}

@media (max-width:760px){
  :root{ --gutter:var(--space-5); --section-pad:var(--space-9); --h1-size:2rem; }
  .panel{ padding-top:var(--section-pad); }   /* phones: the hero below-padding is 48, so 48 + 48 = 96 like the other boundaries */
  .hero{ padding:var(--space-8) var(--space-5) var(--space-9); min-height:0; }
  /* Phone-size hero, compacted so the concierge INPUT (not just its heading) is inside
     the first screen in EN and ES on 375x667+ phones. The subtitle alone is not enough:
     the ES headline takes 4 lines. Measured on iPhone 13, the ES input goes from
     722px (below a 664px screen) to ~564px. (Written for the old order, numbers ->
     card; the order is now portrait -> card -> numbers, see the 900px block.) */
  .hero-sub{ font-size:14.5px; line-height:1.45; }
  .hero-inner{ --hero-gap:var(--space-4); }
  .stat{ padding:var(--space-2) var(--space-4); flex-basis:min(64vw, 250px); }   /* wider = fewer label lines = shorter strip */
  .intake{ padding:var(--space-5); }
  .final-cta-inner{ padding:var(--space-8) var(--space-6); }
  .final-cta-inner .btn{ width:100%; justify-content:center; }   /* full-width tap target; also keeps the long ES label inside the card at 320px */
  .service-row{ grid-template-columns:36px minmax(0,1fr) 112px; padding:var(--space-5); }
  .page-header{ padding:var(--space-10) var(--space-5) var(--space-8); }
  .service-detail{ padding:var(--space-6) var(--space-5); }
  .process-grid{ grid-template-columns:1fr; }
}

@media (max-width:640px){
  .footer{ padding:var(--space-6) var(--space-5) 80px; }
  .footer-inner{ padding:var(--space-5); }
  .nav-cta{ display:none; }
  .nav-logo-tag{ display:none; }
  .nav-inner{ --nav-pad-x:var(--space-5); padding:var(--space-3) var(--nav-pad-x); gap:var(--space-4); }
}

/* Room for the wolf. The icon + its gap add ~25-27px to the logo, and the row does not wrap or shrink (that was the
   old "nav breaks / theme button cut off" bug), so on narrow phones the spare space comes from gaps that were only
   there for breathing room: 16 -> 8 between logo / link / actions and between the two toggles. */
/* Just above the phone layout (641-760px) the full nav (link + EN/ES + theme + CTA) plus the wolf did not fit in Spanish
   ("Iniciar un proyecto" is the longest CTA): it ran off the screen up to ~662px. The side margin now follows --gutter (20px
   here, like every section below the nav; it was a fixed 32px), and the gaps and the CTA's padding give back the rest. */
@media (min-width:641px) and (max-width:760px){
  .nav-inner{ --nav-pad-x:var(--gutter); padding-inline:var(--nav-pad-x); gap:var(--space-4); }
  .nav-cta{ padding-inline:var(--space-4); }
}

@media (max-width:430px){
  .nav-inner{ gap:var(--space-2); }
  .nav-actions{ gap:var(--space-2); }
}

@media (max-width:560px){
  .intake-row{ flex-direction:column; }
  .intake-input{ min-height:96px; } /* ES placeholder wraps to 3 lines */
  .intake-btn{ padding:var(--space-3) var(--space-5); }
}

@media (max-width:360px){
  .nav-inner{ --nav-pad-x:10px; padding:var(--space-3) var(--nav-pad-x); gap:var(--space-2); }   /* 10px side margin (was 12): 320px has no spare width left */
  .nav-logo{ --logo-fs:17px; }
  .lang-toggle{ padding:var(--space-1) var(--space-2); }            /* 12 -> 8px each side of "EN / ES" */
  .nav-link{ padding:var(--space-2) 2px; }
  .nav-actions{ gap:var(--space-2); }
}

/* 320-340px in Spanish ("Servicios" is 9px wider than "Services"): 6px more so the theme button keeps the 10px margin */
@media (max-width:340px){
  .nav-inner{ gap:6px; }
  .nav-actions{ gap:6px; }
}

/* =========================================================
   LEAD-INTAKE CHAT WIDGET  (js/chat-widget.js)
   Same paper/ink system as the rest of the site. Launcher sits
   BELOW the sticky nav (z-index 40 < 50). Nothing here is on the
   critical render path.
   ========================================================= */
.lwc{
  position:fixed; right:20px; bottom:20px; z-index:40;
  font-family:var(--font-body);
}
.lwc-launcher{
  position:relative;
  display:flex; align-items:center; gap:var(--space-2);
  height:44px; padding:0 var(--space-5) 0 var(--space-4);
  border-radius:999px;
  font-family:var(--font-body); font-size:14px; font-weight:600; letter-spacing:-0.01em; white-space:nowrap;
  color:#fff; background:var(--accent); border:1px solid var(--accent); box-shadow:var(--shadow-glow);
  transition:transform .2s var(--ease), background .2s var(--ease), border-color .2s var(--ease), opacity .12s var(--ease), visibility 0s;
}
.lwc-launcher-short{ display:none; }   /* only the <=360px compact pill shows it, see the end of this block */
.lwc-launcher:hover{
  background:var(--accent-strong); border-color:var(--accent-strong);
  transform:translateY(-1px);
}
/* the one legitimate --signal use: a small status dot on the ink pill */
.lwc-ping{
  flex:none; width:8px; height:8px; border-radius:50%;
  background:var(--signal);
  animation:pulse 2s ease-in-out infinite;
}
/* the hero intake card is the CTA while it is on screen (js/main.js) */
html.intake-in-view .lwc[data-open="false"] .lwc-launcher{
  opacity:0; visibility:hidden; pointer-events:none; transform:translateY(8px);
  transition:opacity .2s var(--ease), transform .2s var(--ease), visibility 0s .2s;
}
.lwc[data-open="true"] .lwc-launcher{ display:none; }

/* explicit — a class rule with display:flex would otherwise beat the
   UA [hidden] style and leave the panel covering the launcher */
.lwc-panel[hidden]{ display:none; }
.lwc-panel{
  position:absolute; right:0; bottom:0;
  width:380px; max-width:calc(100vw - 40px);
  height:560px; max-height:calc(100vh - 120px);
  display:flex; flex-direction:column;
  background:var(--panel-bg);
  -webkit-backdrop-filter:blur(16px); backdrop-filter:blur(16px);
  border:1px solid var(--border-strong);
  border-radius:var(--radius-lg);
  overflow:hidden;
  box-shadow:var(--shadow-3);
  animation:lwc-in .22s var(--ease);
}
@keyframes lwc-in{ from{ opacity:0; transform:translateY(12px); } to{ opacity:1; transform:none; } }

.lwc-head{
  display:flex; align-items:center; justify-content:space-between;
  gap:var(--space-4);
  padding:var(--space-4) var(--space-5);
  border-bottom:1px solid var(--border);
}
.lwc-head-text{ display:flex; flex-direction:column; gap:2px; }
.lwc-eyebrow{
  font-family:var(--font-mono); font-size:12px; letter-spacing:0.12em;
  text-transform:uppercase; color:var(--accent-text);
}
.lwc-title{ font-weight:600; font-size:14px; color:var(--ink); }
.lwc-close{
  background:none; border:none; color:var(--ink-soft);
  font-size:22px; line-height:1; width:28px; height:28px;
  display:flex; align-items:center; justify-content:center; border-radius:6px;
  transition:color .2s var(--ease), background .2s var(--ease);
}
.lwc-close:hover{ color:var(--ink); background:rgba(17,19,24,0.06); }

.lwc-log{
  flex:1; overflow-y:auto;
  padding:var(--space-5);
  display:flex; flex-direction:column; gap:var(--space-3);
  scrollbar-width:thin; scrollbar-color:var(--border-strong) transparent;
}
.lwc-log::-webkit-scrollbar{ width:6px; }
.lwc-log::-webkit-scrollbar-thumb{ background:var(--border-strong); border-radius:3px; }

.lwc-msg{
  max-width:85%;
  padding:var(--space-3) var(--space-4);
  border-radius:12px;
  font-size:14px; line-height:1.5;
  white-space:pre-wrap; word-wrap:break-word;
}
.lwc-msg--assistant{
  align-self:flex-start;
  background:var(--surface-2);
  border:1px solid var(--border);
  color:var(--ink);
  border-bottom-left-radius:4px;
}
.lwc-msg--user{
  align-self:flex-end;
  background:var(--accent-dim);
  border:1px solid var(--accent-line);
  color:var(--ink);
  border-bottom-right-radius:4px;
}
.lwc-msg--error{
  align-self:flex-start;
  background:transparent;
  border:1px dashed var(--ink);
  color:var(--ink);
  font-size:13px;
}
.lwc-msg--note{
  align-self:center;
  background:none; border:none; padding:var(--space-1) 0;
  color:var(--label); font-size:12px; text-align:center;
}

.lwc-typing{ display:flex; gap:5px; align-items:center; }
.lwc-typing span{
  width:6px; height:6px; border-radius:50%; background:var(--ink-soft);
  animation:lwc-blink 1.2s ease-in-out infinite;
}
.lwc-typing span:nth-child(2){ animation-delay:.15s; }
.lwc-typing span:nth-child(3){ animation-delay:.3s; }
@keyframes lwc-blink{ 0%,80%,100%{ opacity:.25; } 40%{ opacity:1; } }

.lwc-form{
  display:flex; align-items:flex-end; gap:var(--space-2);
  padding:var(--space-3) var(--space-3) var(--space-3) var(--space-4);
  border-top:1px solid var(--border);
  position:relative;
}
.lwc-hp{
  position:absolute; left:-9999px; top:auto;
  width:1px; height:1px; opacity:0; pointer-events:none;
}
.lwc-input{
  flex:1; resize:none;
  font-family:var(--font-body); font-size:14px; line-height:1.45;
  color:var(--ink);
  background:var(--bg); /* not --surface-2: the --label placeholder needs >=4.5:1 */
  border:1px solid var(--border-strong);
  border-radius:10px;
  padding:var(--space-3) var(--space-3);
  max-height:120px;
  transition:border-color .2s var(--ease);
}
.lwc-input:focus{ outline:none; border-color:var(--accent-text); }
.lwc-input::placeholder{ color:var(--label); }
.lwc-input:disabled{ opacity:.6; }

.lwc-send{
  flex:none;
  width:40px; height:40px; border-radius:10px;
  display:flex; align-items:center; justify-content:center;
  color:#fff; background:var(--accent); border:1px solid var(--accent);
  transition:background .2s var(--ease), opacity .2s var(--ease), transform .2s var(--ease);
}
.lwc-send:hover:not(:disabled){ background:var(--ink); border-color:var(--ink); transform:translateY(-1px); }
.lwc-send:disabled{ opacity:.4; cursor:not-allowed; }

.lwc-foot{
  margin:0; padding:0 var(--space-4) var(--space-3);
  font-family:var(--font-mono); font-size:12px; letter-spacing:0.04em;
  color:var(--label); text-align:center;
}

@media (max-width:480px){
  .lwc{ right:0; left:0; bottom:0; }
  .lwc-launcher{ position:fixed; right:16px; bottom:16px; }
  .lwc-panel{
    position:fixed; right:0; left:0; bottom:0;
    width:100%; max-width:100%;
    height:78vh; max-height:78vh;
    border-radius:var(--radius) var(--radius) 0 0;
  }
}

/* Very small phones (320-360px): the full label made the pill 218-233px wide, 68-73% of a 320px screen, sitting on
   the portrait and on text. Short label -> ~40% of the width, still a 44px-tall target. */
@media (max-width:360px){
  .lwc-launcher{ right:12px; bottom:12px; padding:0 var(--space-4) 0 var(--space-3); font-size:13px; }
  .lwc-launcher-label{ display:none; }
  .lwc-launcher-short{ display:inline; }
}

@media (prefers-reduced-motion: reduce){
  .lwc-panel{ animation:none; }
  .lwc-ping{ animation:none; }
  .lwc-typing span{ animation:none; opacity:.5; }
  .lwc-launcher:hover, .lwc-send:hover:not(:disabled){ transform:none; }
}
