/* ===================================================================
   NICKOLAS TSORVAS — v3.css  (the homepage: "A+ — The Living Index")
   Loaded after site.css on the homepage only. Tokens come from site.css
   (colours, the type scale, --gutter, spacing, --header-h), so dark mode
   and text sizes are inherited without a second set of values.

   Under the shared header: two zones and a floor.
     .v3-index  left  — About link, greeting, teaser, portrait;
                        the moving shapes; the Campaigns heading and list
     .v3-wall   right — the selected campaign's work, as one big link,
                        on a field of the campaign's colour
     .strip     floor — the ticker (desktop; in normal flow on phones)

   The left column is ordinary top-to-bottom flow. Nothing is stretched
   to fill the window and nothing is clipped: if the index is taller than
   the window (a short laptop, a zoomed browser, more campaigns) the page
   scrolls, and the wall stays in view beside it.
   =================================================================== */

.v3{
  --v3-strip:44px;                       /* the ticker's height */
  --v3-floor:var(--v3-strip);            /* how much of the window the ticker takes while it is pinned */
  --geo-blue:#4B62A4;
  display:grid; grid-template-columns:minmax(0,44fr) minmax(0,56fr); grid-template-rows:1fr auto; align-items:start;
  min-height:calc(100vh - var(--header-h));
  min-height:calc(100svh - var(--header-h));
}
html[data-theme="dark"] .v3{--geo-blue:#7C97E6;}

/* ---------- THE INDEX ---------- */
.v3-index{grid-column:1; grid-row:1; min-width:0; padding:clamp(14px,1.6vw,24px) clamp(20px,2.6vw,40px) var(--s4) var(--gutter);}
.v3-index-in{max-width:41rem;}           /* keeps each title and its preview together on very wide screens */

/* ABOUT — always a link. The label's words are editable; its role is not. */
.v3-about{
  display:inline-flex; align-items:center; min-height:44px; padding-right:var(--s2);
  font-family:var(--mono); font-size:var(--fs-label); font-weight:700; letter-spacing:.1em; text-transform:uppercase;
  color:var(--blue); text-decoration:none;
}
.v3-about .mark{margin-right:10px;}
.v3-about-arrow{margin-left:8px; transition:transform .15s ease;}
.v3-about:hover,.v3-about:focus-visible{color:var(--dark);}
.v3-about:hover .v3-about-arrow,.v3-about:focus-visible .v3-about-arrow{transform:translateX(3px);}
@media (prefers-reduced-motion: reduce){ .v3-about-arrow{transition:none;} }

/* the greeting, the teaser and the portrait beside them */
.v3-hello{display:grid; grid-template-columns:minmax(0,1fr) clamp(140px,11vw,168px); gap:clamp(16px,2vw,28px); align-items:start; margin-top:2px;}
.v3-greeting{font-weight:700; font-size:var(--fs-greeting); line-height:1.04; letter-spacing:-.04em;}
.v3-teaser{margin-top:var(--s2); font-size:var(--fs-body); line-height:1.5; max-width:32ch;}
.v3-portrait{width:100%; height:auto; aspect-ratio:3/4; object-fit:cover; object-position:50% 22%;}   /* an upright crop that keeps the whole face */

/* ---------- THE SHAPES ----------
   A shallow band between the teaser and Campaigns. Decoration only:
   hidden from screen readers, never clickable, clipped to its own box, so
   a shape can never cover type, a link or an image, or cross into the
   wall. It has a fixed height, so nothing around it ever moves.

   Motion is CSS transforms only. Each piece ends its loop exactly where
   it began, so the loop has no visible seam.
     desktop  data-motion="geometric"        a slow continuous sequence
     phones   data-motion-mobile="intro"     one short entrance (4.2s), then still
     "still" (either), or the visitor's reduced-motion setting: no movement
   Pause motion (v3.js) and leaving the screen both hold it in place. */
.geo{position:relative; height:72px; margin:var(--s3) 0 var(--s2); overflow:hidden; pointer-events:none;}
.geo i{position:absolute; display:block;}
.geo-strip{left:3%; top:30px; width:84px; height:14px; background:var(--geo-blue); transform:rotate(-8deg);}
.geo-block{left:41%; top:20px; width:30px; height:30px; background:var(--orange); transform:rotate(-10deg);}
.geo-tri{left:62%; top:22px; width:34px; height:30px; background:var(--grape); clip-path:polygon(50% 100%, 0 0, 100% 0);}
.geo-disc{right:6%; top:22px; width:28px; height:28px; border-radius:50%; background:var(--dark); box-shadow:6px 0 0 var(--grape);}
html[data-theme="dark"] .geo-tri{background:#F2D27A;}      /* grape disappears on teal; the triangle takes the lamp's yellow at night */

@media (prefers-reduced-motion: no-preference){
  @media (min-width:861px){
    .geo[data-motion="geometric"] .geo-strip{animation:geoStrip 11s cubic-bezier(.62,.03,.2,1) infinite;}
    .geo[data-motion="geometric"] .geo-block{animation:geoBlock 13s cubic-bezier(.62,.03,.2,1) infinite;}
    .geo[data-motion="geometric"] .geo-tri{animation:geoTri 17s ease-in-out infinite;}
    .geo[data-motion="geometric"] .geo-disc{animation:geoDisc 9s cubic-bezier(.62,.03,.2,1) infinite;}
  }
  @media (max-width:860px){
    .geo[data-motion-mobile="intro"] .geo-strip{animation:geoInLeft 1.5s cubic-bezier(.2,.8,.2,1) .2s both;}
    .geo[data-motion-mobile="intro"] .geo-block{animation:geoInDrop 1.6s cubic-bezier(.2,.8,.2,1) 1.1s both;}
    .geo[data-motion-mobile="intro"] .geo-disc{animation:geoInRight 1.7s cubic-bezier(.2,.8,.2,1) 2.5s both;}
  }
  /* held by the visitor (Pause motion), or while off screen / in a background tab */
  .v3[data-paused] .geo i,.v3 .geo.is-off i{animation-play-state:paused;}   /* one step more specific than the rules that start the motion */
}
@keyframes geoStrip{0%,8%{transform:translateX(0) rotate(-8deg);} 38%,58%{transform:translateX(72px) rotate(6deg);} 88%,100%{transform:translateX(0) rotate(-8deg);}}
/* a square looks the same every quarter turn, so ending half a turn on is a seamless loop */
@keyframes geoBlock{0%,12%{transform:translateY(0) rotate(-10deg);} 30%,48%{transform:translateY(12px) rotate(80deg);} 66%,100%{transform:translateY(0) rotate(170deg);}}
@keyframes geoTri{0%,100%{transform:translateX(0);} 50%{transform:translateX(-46px);}}
@keyframes geoDisc{0%,20%{transform:translate(0,0);} 45%{transform:translate(-44px,0);} 58%{transform:translate(-44px,-10px);} 70%,100%{transform:translate(0,0);}}
@keyframes geoInLeft{from{transform:translateX(-160%) rotate(-8deg);} to{transform:translateX(0) rotate(-8deg);}}
@keyframes geoInDrop{from{transform:translateY(-220%) rotate(-100deg);} to{transform:translateY(0) rotate(-10deg);}}
@keyframes geoInRight{from{transform:translateX(320%);} to{transform:translateX(0);}}

/* ---------- CAMPAIGNS ----------
   A heading (never a link or a button), then one real link per campaign:
   brand and title on the left, a deliberate preview on the right. */
.v3-h{display:flex; align-items:center; font-family:var(--mono); font-size:var(--fs-label); font-weight:700; letter-spacing:.1em; text-transform:uppercase; color:var(--blue); min-height:32px;}
.v3-h .mark{margin-right:10px;}
.v3-work{margin-top:var(--s1);}
.v3-work ol{list-style:none; margin:0; padding:0;}
.v3-row{position:relative;}
.v3-card{
  display:grid; grid-template-columns:minmax(0,1fr) clamp(120px,10.4vw,160px); column-gap:clamp(14px,1.8vw,26px); align-items:center;
  padding:10px 0; text-decoration:none; color:inherit;
}
.v3-card:focus{outline:none;}
.v3-card:focus-visible{outline:3px solid var(--orange); outline-offset:2px;}
.v3-card-text{grid-column:1; grid-row:1; display:block; min-width:0;}
.v3-name{display:block; font-family:var(--mono); font-size:var(--fs-label); font-weight:700; letter-spacing:.06em; text-transform:uppercase; color:var(--blue); margin-top:8px;}
.v3-client{display:block; font-weight:700; text-transform:uppercase; font-size:var(--fs-index-title); line-height:1; letter-spacing:-.04em; overflow-wrap:normal; word-break:normal; hyphens:none;}
.v3-card-idea{display:none;}           /* phones only; desktop shows the idea under the list */

/* the row preview: one frame for every campaign, the image never stretched */
.v3-thumb{grid-column:2; grid-row:1; display:block; aspect-ratio:1/1; overflow:hidden; background:transparent;}
.v3-thumb img{display:block; width:100%; height:100%; object-fit:contain; object-position:center !important;}

/* the selected row: a short orange tick in the margin. Nothing else
   changes and the other rows are never dimmed. */
.v3-row.is-active .v3-card::before{content:''; position:absolute; left:calc(-1*min(var(--gutter) - 6px, 24px)); top:50%; width:min(var(--gutter) - 12px, 16px); height:3px; margin-top:-1px; background:var(--orange);}
.v3-row.is-active .v3-name{color:var(--dark);}

/* the selected campaign's idea, under the list */
.v3-idea{margin-top:var(--s3); min-height:8.4em;}
.v3-idea-text{font-size:var(--fs-body); line-height:1.5; color:var(--muted); max-width:42ch;}
.v3-idea-meta{margin-top:10px;}

/* Pause motion: holds the shapes AND the ticker. Shown only when something moves. */
.v3-motion{
  display:inline-flex; align-items:center; min-height:44px; margin-top:var(--s1); padding:0;
  font-family:var(--mono); font-size:var(--fs-label); letter-spacing:.06em; text-transform:uppercase;
  color:var(--muted); background:none; border:0; cursor:pointer; text-decoration:underline; text-decoration-color:var(--rule-strong); text-underline-offset:5px;
}
.v3-motion:hover,.v3-motion:focus-visible{color:var(--dark); text-decoration-color:var(--blue);}
.v3-motion[hidden]{display:none;}

/* ---------- THE WALL ---------- */
.v3-wall{
  grid-column:2; grid-row:1; align-self:start; position:sticky; top:var(--header-h);
  height:calc(100vh - var(--header-h) - var(--v3-floor));
  height:calc(100svh - var(--header-h) - var(--v3-floor));
  min-height:320px;
  overflow:hidden; background:var(--field, var(--art)); color:var(--ink, #F4EEE2);
}
/* Every campaign uses the same preview area and a separate link row.
   Contain preserves the complete artwork; cover is an explicit CMS choice. */
.v3-stage{
  position:absolute; inset:0; display:grid;
  grid-template-rows:minmax(0,1fr) auto; gap:24px;
  padding:clamp(20px,3vw,48px);
  color:inherit; text-decoration:none;
}
.v3-stage img{
  grid-row:1; display:block; width:100%; height:100%; min-height:0;
  max-width:none; object-fit:contain;
}
.v3-wall[data-fit="contain"] .v3-stage img{object-position:center !important;}
.v3-wall[data-fit="cover"] .v3-stage img{object-fit:cover;}
.v3-stage:focus{outline:none;}
.v3-stage:focus-visible{outline:3px solid var(--orange); outline-offset:-8px;}
/* says, in words, that the artwork is a link and where it goes */
.v3-stage-label{
  grid-row:2; position:static; justify-self:start; max-width:100%;
  font-family:var(--mono); font-size:.875rem; letter-spacing:.06em; text-transform:uppercase; line-height:1.4;
  padding-bottom:4px; border-bottom:1px solid currentColor;
}

/* ---------- THE FLOOR — the ticker ---------- */
.strip{
  grid-column:1 / -1; grid-row:2; position:sticky; bottom:0; z-index:5;
  height:var(--v3-strip); background:#151516; color:#EEE7D8; border-top:3px solid var(--orange);
  display:flex; align-items:center; overflow:hidden;
}
.strip-track{display:flex; white-space:nowrap; will-change:transform;}
.strip-track span{font-family:var(--mono); font-size:var(--fs-label); letter-spacing:.14em; text-transform:uppercase;}
html[data-theme="dark"] .strip{background:var(--night-brown); color:var(--night-text);}
@media (prefers-reduced-motion: no-preference){
  .strip-track{animation:crawl 62s linear infinite;}
  .strip:hover .strip-track,.v3[data-paused] .strip-track,.strip.is-off .strip-track{animation-play-state:paused;}
  @keyframes crawl{from{transform:translateX(0);} to{transform:translateX(-50%);}}
}

/* very short windows: the ticker stops being pinned and sits at the end of
   the page, so it never takes room from the work */
@media (min-width:861px) and (max-height:600px){
  .v3{--v3-floor:0px;}
  .strip{position:static;}
}

/* ---------- PHONES + TABLET PORTRAIT ----------
   One column, in the same order: About, greeting + teaser beside a compact
   portrait, the shapes, Campaigns, then full-width cards — brand, title,
   the artwork, the idea. Every card is one link: one tap opens it. There
   is no wall, no hover state, no small duplicate preview, and nothing
   pinned to the bottom of the screen. */
@media (max-width:860px){
  .v3{display:block; min-height:0; --v3-strip:40px;}
  .v3-index{padding:6px var(--gutter) var(--s5);}
  .v3-index-in{max-width:none;}
  .v3-hello{grid-template-columns:minmax(0,1fr) clamp(90px,26vw,112px); gap:16px;}
  .v3-teaser{margin-top:12px; max-width:none;}
  .v3-portrait{object-position:50% 16%;}
  .geo{height:44px; margin:14px 0 8px;}
  .geo-strip{width:58px; height:11px; top:16px;}
  .geo-block{width:20px; height:20px; top:12px; left:46%;}
  .geo .geo-tri{display:none;}                            /* phones carry three pieces, not four */
  .geo-disc{width:21px; height:21px; top:12px; right:8%; box-shadow:5px 0 0 var(--grape);}
  .v3-work{margin-top:var(--s2);}
  .v3-row + .v3-row{margin-top:var(--s5);}
  .v3-card{display:block; padding:0;}
  .v3-row.is-active .v3-card::before{display:none;}
  .v3-row.is-active .v3-name{color:var(--blue);}
  .v3-client{font-size:clamp(1.875rem,1.2rem + 3.8vw,2.25rem); line-height:1.03;}
  .v3-thumb{margin-top:14px; aspect-ratio:auto; overflow:visible; background:none;}
  .v3-thumb img{height:auto; object-fit:contain;}
  .v3-card-idea{display:block; margin-top:12px; font-size:var(--fs-body); line-height:1.48; color:var(--muted);}
  .v3-idea{display:none;}
  .v3-motion{margin-top:var(--s4);}
  .v3-wall{display:none;}
  .strip{position:static;}
}
/* very narrow phones, or a larger text size chosen in the browser (em here
   follows that setting): the portrait drops under the words rather than
   squeezing them */
@media (max-width:21.5em){
  .v3-hello{grid-template-columns:minmax(0,1fr);}
  .v3-portrait{width:112px;}
}


/* ===================================================================
   DESKTOP FIT — every campaign and the selected idea on one screen

   From 861px wide the left column is sized to the window, so the About
   link, greeting, portrait, shapes, every campaign row, the selected
   idea, Pause motion and the ticker are all visible without scrolling.
   Phones and tablets (860px and under) keep the scrolling card list.

   It fits by spending less on spacing, the portrait and the row
   previews. Nothing is scaled, hidden, cut off or locked: if the window
   is very short, the text is enlarged, or more campaigns are shown than
   fit, the page simply scrolls as it always did.

   THE SUM. The room under the header and above the ticker is
   --index-room. Everything except the row previews takes about
   --index-rest plus the portrait's height. What is left is shared
   between the rows (--index-rows) and becomes the preview size, held
   between --index-thumb-min and 112px. A row can never be shorter than
   its two lines of text, which is why the smallest preview is 48px.

   Type sizes are in rem, so a larger text size chosen in the browser
   still enlarges them (and the page then scrolls).
   =================================================================== */
@media (min-width:861px) {
  .v3 {
    --v3-strip:36px;
    --v3-floor:var(--v3-strip);
    --index-vh:100vh;
    --index-rows:4;
    --index-rest:280px;                  /* paddings, About, shapes, heading, idea (room for three lines), Pause motion */
    --index-thumb-min:48px;
    --index-portrait:clamp(72px, calc(var(--index-vh) * .1 - 6px), 104px);
    --index-room:calc(var(--index-vh) - var(--header-h) - var(--v3-strip));
    --index-thumb:clamp(var(--index-thumb-min), calc((var(--index-room) - var(--index-rest) - var(--index-portrait) * 4 / 3) / var(--index-rows) - 12px), 112px);
    grid-template-columns:minmax(0,49fr) minmax(0,51fr);
  }
  /* the row count, so three campaigns get larger previews and five or six get smaller ones */
  .v3:has(.v3-row:nth-child(3):last-child) {--index-rows:3;}
  .v3:has(.v3-row:nth-child(5):last-child) {--index-rows:5;}
  .v3:has(.v3-row:nth-child(6)) {--index-rows:6;}

  .v3-index {padding:12px clamp(20px,2vw,32px) 12px var(--gutter);}
  .v3-index-in {max-width:none;}
  .v3-about {min-height:24px;}
  .v3-hello {grid-template-columns:minmax(0,1fr) var(--index-portrait);gap:16px;margin-top:6px;}
  .v3-greeting {font-size:clamp(1.625rem,2.2vw,2.125rem);}
  .v3-teaser {font-size:1rem;line-height:1.4;margin-top:8px;max-width:38ch;}
  .geo {height:28px;margin:12px 0 4px;}
  .geo-strip {top:10px;height:10px;width:68px;}
  .geo-block {top:3px;width:22px;height:22px;}
  .geo-tri {top:4px;width:26px;height:22px;}
  .geo-disc {top:4px;width:22px;height:22px;}
  .v3-h {min-height:24px;}
  .v3-work {margin-top:4px;}
  .v3-card {grid-template-columns:minmax(0,1fr) var(--index-thumb);column-gap:16px;padding:6px 0;}
  .v3-client {font-size:clamp(1.5rem,2.15vw,2.125rem);line-height:1.02;}
  .v3-name {font-size:.6875rem;line-height:1.25;margin-top:5px;}
  .v3-thumb {aspect-ratio:1 / 1;background:transparent;}
  .v3-thumb img {width:100%;height:100%;object-fit:contain;object-position:50% 50% !important;}   /* the whole image, never cropped */
  .v3-idea {min-height:0;margin-top:12px;}
  .v3-idea-text {font-size:1rem;line-height:1.4;max-width:52ch;}
  .v3-idea-meta {margin-top:6px;font-size:.6875rem;line-height:1.4;gap:6px 12px;}
  .v3-motion {min-height:24px;margin-top:8px;font-size:.6875rem;}
  .v3-wall {min-height:0;}
  .strip {position:sticky;}
}
/* a narrow desktop window: the copy wraps onto more lines, so the previews give up a little more */
@media (min-width:861px) and (max-width:1100px) {
  .v3 {--index-rest:324px;}
}
/* the small-viewport unit, where the browser has it (it ignores a phone-style collapsing toolbar) */
@supports (height:100svh) {
  @media (min-width:861px) { .v3 {--index-vh:100svh;} }
}
/* a short window: a laptop with the browser's toolbars showing */
@media (min-width:861px) and (max-height:760px) {
  .v3 {--index-rest:252px;--index-portrait:72px;}
  .v3-index {padding-top:8px;padding-bottom:8px;}
  .v3-about {min-height:22px;font-size:.6875rem;}
  .v3-hello {margin-top:4px;}
  .v3-greeting {font-size:1.625rem;}
  .v3-teaser {font-size:.9375rem;line-height:1.35;margin-top:6px;}
  .geo {height:22px;margin-top:8px;margin-bottom:2px;}
  .geo-strip {top:6px;}
  .geo-block,.geo-tri,.geo-disc {top:0;}
  .v3-h {min-height:20px;font-size:.6875rem;}
  .v3-client {font-size:1.5rem;}
  .v3-idea {margin-top:8px;}
  .v3-idea-text {font-size:.9375rem;line-height:1.35;}
  .v3-idea-meta {font-size:.625rem;margin-top:5px;gap:4px 8px;}
  .v3-motion {min-height:22px;margin-top:5px;}
}
/* a very short window: a 768px-tall laptop screen with the browser's toolbars showing */
@media (min-width:861px) and (max-height:680px) {
  .v3 {--index-rest:226px;--index-portrait:60px;--index-thumb-min:40px;}
  .v3-index {padding-top:6px;padding-bottom:6px;}
  .v3-hello {gap:12px;}
  .geo {height:18px;margin-top:6px;}
  .geo-strip {top:5px;height:8px;width:56px;}
  .geo-block {top:1px;width:16px;height:16px;}
  .geo-tri {top:1px;width:20px;height:16px;}
  .geo-disc {top:1px;width:16px;height:16px;box-shadow:4px 0 0 var(--grape);}
  .v3-card {padding:4px 0;}
  .v3-idea {margin-top:6px;}
}
/* Natural scrolling remains available at extreme zoom / very short heights.
   Do not add body overflow:hidden, transforms, or an inner list scrollbar. */

@media (min-width:861px) {
  .v3 { --index-portrait:clamp(140px,11vw,168px); }
}
