/* =============================================================================
   Fisher Digital Design — gateway landing page
   Full-screen three-door selector for the root domain. Tokens carried from
   the live fisherdigitaldesign.com styles.css + effects-site theme.css.
   Layout is normal flow + flexbox throughout (no fixed header, no raw 100vh
   on the shell — both broke in sandboxed iframe previews).
   ========================================================================== */

:root {
  --canvas:   #08090b;
  --surface:  #101216;
  --ink:      #f5f6f7;
  --body-txt: #c8d1de;
  --muted:    #8b93a1;
  --accent:   #01a9fa;
  --hairline: rgba(255, 255, 255, 0.08);

  --font-display: 'Unbounded', ui-sans-serif, system-ui, sans-serif;
  --font-body:    'Inter', ui-sans-serif, system-ui, -apple-system, sans-serif;
  --font-mono:    'JetBrains Mono', ui-monospace, Consolas, monospace;

  --pad: clamp(20px, 4vw, 64px);
  --ease-door: cubic-bezier(0.22, 1, 0.36, 1);
}

* { margin: 0; padding: 0; box-sizing: border-box; }

html { height: 100%; }

body {
  min-height: 100%;
  display: flex;
  flex-direction: column;
  background: var(--canvas);
  color: var(--ink);
  font-family: var(--font-body);
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}

/* Header --------------------------------------------------------------------
   Normal document flow. Wordmark tracks in during the entrance beat. */
.head {
  padding: clamp(22px, 3.5vh, 36px) var(--pad) clamp(18px, 3vh, 30px);
  text-align: center;
  border-bottom: 1px solid var(--hairline);
}
.head__eyebrow {
  font-family: var(--font-mono);
  font-size: 10px;
  font-weight: 500;
  letter-spacing: 0.42em;
  text-indent: 0.42em;
  text-transform: uppercase;
  color: var(--muted);
  animation: gw-fade 0.9s ease 1.05s both;
}
.head__mark {
  margin-top: 14px;
  line-height: 0;                 /* the h1 is just the logo image */
  animation: gw-logo-in 1.2s var(--ease-door) 0.1s both;
}
.head__logo {
  height: clamp(30px, 4.5vw, 46px);
  width: auto;
  max-width: min(80vw, 440px);
  object-fit: contain;
}

/* Doors — the three-way split ---------------------------------------------- */
.doors {
  flex: 1;
  display: flex;
  min-height: 420px;
}

.door {
  position: relative;
  flex: 1 1 0;
  min-width: 0;
  display: block;
  overflow: hidden;
  text-decoration: none;
  background: var(--canvas);
  transition: flex-grow 0.65s var(--ease-door);
  animation: gw-rise 0.95s var(--ease-door) both;
}
.door--studio   { animation-delay: 0.35s; }
.door--effects  { animation-delay: 0.50s; }
.door--services { animation-delay: 0.65s; }
.door + .door { border-left: 1px solid var(--hairline); }

.door:focus-visible {
  outline: none;
  box-shadow: inset 0 0 0 2px var(--accent);
}

/* Expansion — hovered/focused door grows, siblings compress (desktop only) */
@media (hover: hover) and (min-width: 821px) {
  .doors:has(.door:hover, .door:focus-visible) .door { flex-grow: 0.72; }
  .doors:has(.door:hover, .door:focus-visible) .door:hover,
  .doors:has(.door:hover, .door:focus-visible) .door:focus-visible { flex-grow: 2.4; }
}

/* Background layers ---------------------------------------------------------
   Every door: bg treatment → accent glow → darkening veil → content. */
.door__bg {
  position: absolute;
  inset: 0;
  pointer-events: none;
}

.door__glow {
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: radial-gradient(120% 90% at 50% 110%, rgba(1, 169, 250, 0.14), transparent 60%);
  opacity: 0;
  transition: opacity 0.6s ease;
}
.door:hover .door__glow,
.door:focus-visible .door__glow { opacity: 1; }

.door__veil {
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: linear-gradient(180deg, rgba(8, 9, 11, 0.42) 0%, rgba(8, 9, 11, 0.2) 45%, rgba(8, 9, 11, 0.88) 100%);
  transition: opacity 0.6s ease;
}
.door:hover .door__veil,
.door:focus-visible .door__veil { opacity: 0.82; }

/* Studio — blueprint grid (static; the drafting canvas above it supplies the
   motion, and its strokes stay aligned to these lines) */
.door__grid {
  background-image:
    repeating-linear-gradient(0deg,  rgba(255, 255, 255, 0.055) 0 1px, transparent 1px 80px),
    repeating-linear-gradient(90deg, rgba(255, 255, 255, 0.055) 0 1px, transparent 1px 80px),
    repeating-linear-gradient(0deg,  rgba(255, 255, 255, 0.022) 0 1px, transparent 1px 16px),
    repeating-linear-gradient(90deg, rgba(255, 255, 255, 0.022) 0 1px, transparent 1px 16px);
  opacity: 0.9;
  transition: opacity 0.6s ease;
}
.door:hover .door__grid,
.door:focus-visible .door__grid { opacity: 1; }

/* Studio — self-drawing wireframes / grid pulses (driven by gateway.js) */
.door__blueprint { width: 100%; height: 100%; display: block; }

/* Effects — live constellation canvas (driven by gateway.js) */
.door__constellation { width: 100%; height: 100%; display: block; }

/* Services — slow-scrolling rate-line texture (rows built by gateway.js) */
.door__rates {
  overflow: hidden;
  /* centre-weighted fade: full brightness at the middle focal band, easing
     out toward the top/bottom edges */
  mask-image: linear-gradient(180deg, transparent, rgba(0, 0, 0, 0.68) 18%, #000 42%, #000 58%, rgba(0, 0, 0, 0.68) 82%, transparent);
  -webkit-mask-image: linear-gradient(180deg, transparent, rgba(0, 0, 0, 0.68) 18%, #000 42%, #000 58%, rgba(0, 0, 0, 0.68) 82%, transparent);
}
.door__rates-inner {
  position: absolute;
  left: 0;
  right: 0;
  animation: gw-rates-scroll 70s linear infinite;
}
.rate-row {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 16px;
  padding: 0 clamp(18px, 2.4vw, 40px);
  border-bottom: 1px solid rgba(255, 255, 255, 0.04);
  font-family: var(--font-mono);
  font-size: 11px;
  line-height: 34px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  white-space: nowrap;
  color: rgba(245, 246, 247, 0.58);
  transition: color 0.4s ease;
}
.rate-row b {
  font-weight: 500;
  color: rgba(1, 169, 250, 0.78);
  transition: color 0.4s ease;
}
@media (hover: hover) and (min-width: 821px) {
  .door:hover .rate-row,
  .door:focus-visible .rate-row { color: rgba(245, 246, 247, 1); }
  .door:hover .rate-row b,
  .door:focus-visible .rate-row b { color: rgba(1, 169, 250, 1); }
  /* Services hover: brighten the CENTRE focal band only. Keep the centre-weighted
     mask (do NOT widen it) so top/bottom rows stay dim — the door title/desc sits
     over the bottom and must not be overshadowed. Veil lifts partway (bottom stays
     dark for content contrast); bloom on the rows helps the centre pop. */
  .door--services:hover .door__veil,
  .door--services:focus-visible .door__veil { opacity: 0.5; }
  .door--services:hover .rate-row,
  .door--services:focus-visible .rate-row { text-shadow: 0 0 10px rgba(255, 255, 255, 0.4); }
  .door--services:hover .rate-row b,
  .door--services:focus-visible .rate-row b { text-shadow: 0 0 18px rgba(1, 169, 250, 0.8); }
}
@keyframes gw-rates-scroll {
  from { transform: translate3d(0, 0, 0); }
  to   { transform: translate3d(0, -50%, 0); }      /* inner holds 2 copies → seamless */
}

/* Door content -------------------------------------------------------------- */
.door__content {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 1;              /* always above the veil, in every layout mode */
  padding: var(--pad);
  padding-bottom: clamp(28px, 5vh, 56px);
}

.door__label {
  font-family: var(--font-mono);
  font-size: 10px;
  font-weight: 500;
  letter-spacing: 0.3em;
  text-transform: uppercase;
  color: var(--accent);
}

.door__title {
  margin-top: 14px;
  font-family: var(--font-display);
  font-weight: 300;
  font-size: clamp(26px, 3.2vw, 52px);
  letter-spacing: 0.01em;
  color: var(--ink);
  transform-origin: 0 100%;
  transition: letter-spacing 0.6s var(--ease-door), transform 0.65s var(--ease-door);
}
.door:hover .door__title,
.door:focus-visible .door__title { letter-spacing: 0.06em; }
/* compressed siblings: titles scale down so nothing clips */
@media (hover: hover) and (min-width: 821px) {
  .doors:has(.door:hover, .door:focus-visible) .door:not(:hover):not(:focus-visible) .door__title {
    transform: scale(0.68);
  }
}

.door__teaser {
  margin-top: 12px;
  font-size: 14px;
  font-weight: 500;
  letter-spacing: 0.01em;
  color: var(--muted);
  transition: color 0.4s ease;
}
.door:hover .door__teaser,
.door:focus-visible .door__teaser { color: var(--ink); }

/* Description — hidden until the door expands (always visible on mobile) */
.door__desc {
  max-width: 38ch;
  margin-top: 0;
  font-size: 15px;
  line-height: 1.65;
  color: var(--body-txt);
  max-height: 0;
  opacity: 0;
  transform: translateY(10px);
  overflow: hidden;
  transition: max-height 0.6s var(--ease-door), opacity 0.45s ease 0.1s,
              transform 0.6s var(--ease-door), margin-top 0.6s var(--ease-door);
}
.door:hover .door__desc,
.door:focus-visible .door__desc {
  max-height: 160px;
  opacity: 1;
  transform: none;
  margin-top: 14px;
}

.door__url {
  margin-top: 20px;
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 0.08em;
  color: var(--accent);
  white-space: nowrap;      /* crops cleanly on compressed doors instead of wrapping */
}
.door__arrow {
  display: inline-block;
  margin-left: 8px;
  transition: transform 0.4s var(--ease-door);
}
.door:hover .door__arrow,
.door:focus-visible .door__arrow { transform: translateX(6px); }

/* Film grain ------------------------------------------------------------------
   Same treatment queued for the effects site — one shared finish layer. */
.grain {
  position: fixed;
  inset: -30%;
  width: 160%;
  height: 160%;
  pointer-events: none;
  z-index: 9000;
  opacity: 0.05;
  will-change: transform;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='300' height='300'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
  animation: gw-grain 0.7s steps(1) infinite;
}
@keyframes gw-grain {
  0%   { transform: translate3d(0, 0, 0); }
  25%  { transform: translate3d(-2%, 3%, 0); }
  50%  { transform: translate3d(3%, -2%, 0); }
  75%  { transform: translate3d(-3%, -3%, 0); }
  100% { transform: translate3d(0, 0, 0); }
}

/* Entrance keyframes ----------------------------------------------------------- */
@keyframes gw-rise {
  from { opacity: 0; transform: translateY(28px); }
  to   { opacity: 1; transform: none; }
}
@keyframes gw-fade {
  from { opacity: 0; }
  to   { opacity: 1; }
}
@keyframes gw-logo-in {
  from { opacity: 0; transform: translateY(-8px) scale(0.96); }
  to   { opacity: 1; transform: none; }
}

/* Leaving — clicked door fills the screen before navigation (gateway.js) ------- */
body.leaving .door { pointer-events: none; }
body.leaving .doors .door:not(.door--active) { flex-grow: 0.0001; }
body.leaving .doors .door--active { flex-grow: 50; }
body.leaving .door--active .door__veil { opacity: 0.25; }
body.leaving .door--active .door__content { opacity: 0; transition: opacity 0.4s ease; }
body.leaving .head { opacity: 0.2; transition: opacity 0.6s ease; }

/* Ticker warp — Services door exit: the door's dimmed rate rows accelerate,
   streak upward with motion blur, and fill the widening door as we travel.
   The landing page's ticker starts fast and decelerates to cruise, so the
   preview literally becomes the page. gateway.js adds body.warping only for
   the services door. The warp animation overrides the idle 70s scroll loop —
   the rows repeat identically, so the restart-from-zero jump is invisible. --- */
body.warping .door--active .door__rates-inner {
  animation: gw-rates-warp 2.2s forwards;   /* easing set per keyframe segment */
  will-change: transform, filter;
}
/* FULL brightness during the click-warp — pure white names + hot accent rates
   with bloom. Was 0.34/0.75 which read DIMMER than the resting door; the warp
   should be the brightest moment, not the dimmest. */
body.warping .door--active .rate-row {
  color: #ffffff;
  text-shadow: 0 0 14px rgba(255, 255, 255, 0.6), 0 0 4px rgba(255, 255, 255, 0.9);
  transition: none;
}
body.warping .door--active .rate-row b {
  color: #8ad6ff;
  text-shadow: 0 0 30px rgba(1, 169, 250, 1), 0 0 10px rgba(180, 230, 255, 1);
  transition: none;
}
/* two full pattern-heights of travel: slow build (65% of the time for the
   first height), then a hard-accelerating sprint. The 65%→65.01% wrap jumps
   -50% → 0 between identical halves, so the seam is invisible. */
@keyframes gw-rates-warp {
  0%     { transform: translate3d(0, 0, 0);    filter: blur(0);
           animation-timing-function: cubic-bezier(0.7, 0, 0.85, 0.6); }
  64.99% { transform: translate3d(0, -50%, 0); filter: blur(0.5px); }
  65%    { transform: translate3d(0, 0, 0);    filter: blur(0.5px);
           animation-timing-function: cubic-bezier(0.35, 0, 1, 0.4); }
  100%   { transform: translate3d(0, -50%, 0); filter: blur(2px); }
}

/* Mobile door exit (Effects + Services): the full desktop effects are keyed to
   the 3-column layout and don't fit the stacked phone layout, so on mobile the
   tap triggers a quick branded accent flash from the tap point that fills and
   fades to canvas-black, then the subsite loads (its hero fades up from black).
   Pure CSS — reliable on every phone. gateway.js adds body.mobi-exit + --nova-x/y. */
body.mobi-exit::after {
  content: '';
  position: fixed;
  inset: 0;
  z-index: 221;
  pointer-events: none;
  background: radial-gradient(circle at var(--nova-x, 50%) var(--nova-y, 50%),
    #eaf7ff 0%, rgba(1, 169, 250, 0.9) 14%, rgba(1, 169, 250, 0.28) 38%, rgba(8, 9, 11, 0) 64%);
  opacity: 0;
  animation: gw-mobi-flash 0.9s ease-in forwards;
}
body.mobi-exit::before {
  content: '';
  position: fixed;
  inset: 0;
  z-index: 220;
  pointer-events: none;
  background: var(--canvas);
  opacity: 0;
  animation: gw-mobi-black 0.9s ease-in forwards;
}
@keyframes gw-mobi-flash {
  0%   { opacity: 0; transform: scale(0.55); }
  28%  { opacity: 1; transform: scale(1.15); }
  100% { opacity: 0; transform: scale(1.9); }
}
@keyframes gw-mobi-black {
  0%   { opacity: 0; }
  50%  { opacity: 0; }
  100% { opacity: 1; }
}

/* Nova flash — Effects door exit: the constellation collapses into the click
   point (driven by gateway.js), then this bloom detonates over the core right
   before travel. The effects site's particle hero assembles on arrival —
   collapse in, big-bang out. gateway.js adds body.collapsing + --nova-x/y. --- */
body.collapsing::after {
  content: '';
  position: fixed;
  inset: 0;
  z-index: 210;
  pointer-events: none;
  background: radial-gradient(circle at var(--nova-x, 50%) var(--nova-y, 50%),
    #eaf7ff 0%, rgba(1, 169, 250, 0.85) 16%, rgba(1, 169, 250, 0.3) 42%, rgba(8, 9, 11, 0) 68%);
  transform-origin: var(--nova-x, 50%) var(--nova-y, 50%);
  opacity: 0;
  animation: gw-nova 1.05s ease-in-out 1.15s forwards;
}
/* bloom over the detonation, then clear to reveal the planet forming */
@keyframes gw-nova {
  0%   { opacity: 0; transform: scale(0.55); }
  40%  { opacity: 1; transform: scale(1.25); }
  100% { opacity: 0; transform: scale(1.9); }
}

/* dip-to-black curtain — the formed sphere holds a beat, then the whole gateway
   fades to canvas-black just before travel. The effects hero fades UP from the
   same black on arrival, so the page swap is invisible and the two moments read
   as one continuous bloom (collapse → sphere → black → hero blooms back). */
body.collapsing::before {
  content: '';
  position: fixed;
  inset: 0;
  z-index: 215;
  pointer-events: none;
  background: var(--canvas);
  opacity: 0;
  animation: gw-blackout 0.6s ease-in 2.8s forwards;
}
@keyframes gw-blackout {
  from { opacity: 0; }
  to   { opacity: 1; }
}

/* Blueprint draft — Studio door exit: the door's wireframe motif takes the
   whole screen. Accent strokes race out and plot a full page skeleton —
   header, hero, columns, dimension ticks — like a CAD file drawing itself.
   Then we travel, and the studio's own masked entrance reveal "builds" the
   real thing. gateway.js adds body.drafting only for the studio door.
   Strokes draw via pathLength/stroke-dashoffset — GPU-cheap, no layout. ----- */
.gw-draft {
  position: fixed;
  inset: 0;
  z-index: 200;
  pointer-events: none;
  opacity: 0;
  background: rgba(8, 9, 11, 0.94);
}
body.drafting .gw-draft {
  opacity: 1;
  transition: opacity 0.22s ease;
  /* "plan approved" beat — the finished draft blooms once before travel */
  animation: gw-draft-approve 0.4s ease 1.55s forwards;
}
@keyframes gw-draft-approve {
  to { filter: drop-shadow(0 0 12px rgba(1, 169, 250, 0.6)); }
}
.gw-draft .draw {
  fill: none;
  stroke: rgba(1, 169, 250, 0.85);
  stroke-width: 1.5;
  vector-effect: non-scaling-stroke;
  stroke-dasharray: 1;
  stroke-dashoffset: 1;
}
body.drafting .gw-draft .draw {
  animation: gw-draw 0.42s cubic-bezier(0.3, 0, 0.35, 1) forwards;
  animation-delay: var(--d, 0s);
}
@keyframes gw-draw { to { stroke-dashoffset: 0; } }
.gw-draft text {
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 0.08em;
  fill: rgba(1, 169, 250, 0.55);
  opacity: 0;
}
body.drafting .gw-draft text {
  animation: gw-fade 0.2s ease forwards;
  animation-delay: var(--d, 0.55s);
}

/* Custom cursor (built by cursor.js — elements only exist on fine pointers) ---- */
html.fdl-cursor-on,
html.fdl-cursor-on * { cursor: none !important; }

.fdl-cur {
  position: fixed;
  top: 0;
  left: 0;
  pointer-events: none;
  z-index: 9999;
  will-change: transform;
}
.fdl-cur--dot {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--accent);
  box-shadow: 0 0 8px rgba(1, 169, 250, 0.8);
}
.fdl-cur--ring {
  width: 36px;
  height: 36px;
  border-radius: 50%;
  border: 1.5px solid rgba(1, 169, 250, 0.6);
  display: flex;
  align-items: center;
  justify-content: center;
  transition: width 0.28s cubic-bezier(0.3, 1.4, 0.4, 1), height 0.28s cubic-bezier(0.3, 1.4, 0.4, 1),
              border-color 0.25s ease, background-color 0.25s ease;
}
.fdl-cur__label {
  font-family: var(--font-mono);
  font-size: 9px;
  letter-spacing: 0.24em;
  text-indent: 0.24em;
  text-transform: uppercase;
  color: var(--accent);
  opacity: 0;
  transition: opacity 0.2s ease;
  white-space: nowrap;
}
.fdl-cur--wake {
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: var(--accent);
  opacity: 0;
}
/* over a door: ring blooms, ENTER label appears */
html.fdl-cur-zone .fdl-cur--ring {
  width: 72px;
  height: 72px;
  border-color: rgba(1, 169, 250, 0.9);
  background-color: rgba(1, 169, 250, 0.06);
}
html.fdl-cur-zone .fdl-cur__label { opacity: 1; }
/* over any other link: ring snaps tight and brightens */
html.fdl-cur-link .fdl-cur--ring {
  width: 28px;
  height: 28px;
  border-color: #bfe7ff;
  background-color: rgba(127, 212, 255, 0.08);
}
html.fdl-cur-link .fdl-cur--dot { background: #fff; }
html.fdl-cur-hide .fdl-cur { visibility: hidden; }
/* click: ring-burst pulse */
.fdl-burst {
  position: fixed;
  width: 14px;
  height: 14px;
  border-radius: 50%;
  border: 1.5px solid #7fd4ff;
  pointer-events: none;
  z-index: 9998;
  animation: fdl-burst 0.5s ease-out forwards;
}
@keyframes fdl-burst {
  from { opacity: 0.9; transform: translate(-50%, -50%) scale(1); }
  to   { opacity: 0;   transform: translate(-50%, -50%) scale(5.5); }
}

/* Mobile — stacked tappable blocks, no hover dependence ------------------------ */
@media (max-width: 820px) {
  .doors { flex-direction: column; min-height: 0; }
  /* Services ticker-warp on a phone: the tapped door leaves the stacked column
     and fills the whole screen so the bright streaking ticker plays full-screen
     (then it navigates to the services site). gateway.js adds warping + active. */
  body.warping .door--active {
    position: fixed;
    inset: 0;
    z-index: 95;
    min-height: 100vh;
    min-height: 100svh;
    border: none;
  }
  body.warping .door--active .door__content { opacity: 0; transition: opacity 0.25s ease; }
  body.warping .head { opacity: 0.15; transition: opacity 0.4s ease; }
  /* each door is nearly a full screen — one at a time, with its background
     animation given room to breathe above the copy */
  .door {
    flex: none;
    min-height: 76vh;
    min-height: 76svh;
    display: flex;
    align-items: flex-end;
  }
  .door + .door {
    border-left: none;
    border-top: 1px solid var(--hairline);
  }
  /* content stays in normal flow (door grows to fit it) but must be
     position:relative — static content paints UNDER the absolute veil */
  .door__content {
    position: relative;
    width: 100%;
    padding-top: 48px;
    padding-bottom: 32px;
  }
  /* content paints above the veil now, so the backgrounds can run nearly
     clear — dark only at the bottom, directly behind the copy */
  .door__veil {
    background: linear-gradient(180deg, rgba(8, 9, 11, 0.08) 0%, rgba(8, 9, 11, 0.05) 45%, rgba(8, 9, 11, 0.78) 100%);
  }
  /* no hover states here — run every background at full presence */
  .door__grid { opacity: 1; }
  .rate-row { color: rgba(245, 246, 247, 0.42); }
  .rate-row b { color: rgba(1, 169, 250, 0.6); }
  .door__desc {
    max-height: none;
    opacity: 1;
    transform: none;
    margin-top: 12px;
    font-size: 14px;
  }
  .head__logo { height: 34px; }
}

/* Reduced motion — everything settles instantly, nothing loops ------------------ */
@media (prefers-reduced-motion: reduce) {
  .head__eyebrow, .head__mark, .door { animation: none; }
  .door__rates-inner, .grain { animation: none; }
  .door, .door__desc, .door__title, .door__arrow, .door__veil, .door__glow,
  .door__teaser { transition: none; }
}
