/* ============================================================================
   CENTRE CITY MALL — PAGE COMPOSITIONS
   ========================================================================== */

/* =============================================================== HERO ====
   Full screen. One photograph of the building running edge to edge and top to
   bottom, the headline stacked in three lines with the middle one in gold, and
   two buttons.

   Jul 31 2026 — turned up. The shape was right and the execution was the
   single most default hero on the internet: a photograph, a flat grey-black
   scrim over the whole of it, and static type. Three changes:

     1. THE WASH IS THE BRAND, NOT GREY. Navy from the left and wine up from
        the floor, both at real saturation, with a poui glow behind the corner
        of the building. The photograph is a grey-green building under a white
        Trinidad sky; a black scrim on it produces grey, and grey is what the
        whole page was inheriting. The coloured wash makes the same photo warm.
     2. THE TYPE IS BIGGER THAN THE PHOTOGRAPH. 5.9rem -> 8.2rem and the
        leading pulled to 0.86, so the three lines lock into one block of
        letterforms that bleeds past the shell's left gutter. A headline the
        same size as everyone else's headline is the definition of bland.
     3. THE LINES ARRIVE. Each of the three rises out of its own clip on load,
        90ms apart. Held to 520ms total: this is above the fold, so it is the
        one animation on the site that a visitor cannot choose to skip.
   ======================================================================== */
.hero {
  position: relative;
  min-height: 100svh;
  display: flex;
  align-items: center;
  padding-block: clamp(6rem, 16vh, 10rem) clamp(3rem, 8vh, 5rem);
  margin-top: calc(var(--header-h) * -1);   /* the photo starts above the bar */
  overflow: hidden;
  isolation: isolate;
  background: var(--navy-band-2);
}
/* Over-tall so the parallax shift has somewhere to go — without the bleed,
   drifting the photo exposes the band colour at one edge. The bleed is in vh
   and NOT in %, because runParallax() computes its shift as a fraction of the
   viewport height: a percentage bleed is a fraction of the element instead, so
   the two only agree by accident and the photo tears off its own box on any
   window the author did not happen to test. --bleed must exceed the element's
   data-parallax rate expressed in vh. Here: 14 > 11.
   The drift animation lives on the img and the parallax on the wrapper,
   because two things cannot own one transform. */
.hero__bg {
  position: absolute; inset: -14vh 0; z-index: -3;
  /* The wrapper clips, not just .hero. heroDrift scales the photograph to
     1.14, which is 1642px on a 1440px window, and that width was reaching
     document.scrollWidth even though .hero's own overflow:hidden was painting
     it correctly — only body's overflow-x:hidden was stopping the page from
     panning. Clipping here means nothing depends on that backstop. */
  overflow: hidden;
  transform: translate3d(0, var(--parallax-y, 0px), 0);
  will-change: transform;
}
.hero__bg img {
  width: 100%; height: 100%;
  object-fit: cover;
  object-position: 62% 48%;
  animation: heroDrift 26s var(--e-soft) infinite alternate;
}
/* A slow push in, and the photo also rides the scroll (see [data-parallax] in
   app.js) so the building sinks as the page moves over it. */
@keyframes heroDrift {
  from { transform: scale(1.04); }
  to   { transform: scale(1.14); }
}
@media (prefers-reduced-motion: reduce) { .hero__bg img { animation: none; } }

/* Navy from the left, wine off the floor, poui glow at the building's corner.
   The three layers stack darkest-first so the headline always has ground under
   it and the sign in the photograph stays legible through the gap. */
.hero__wash {
  position: absolute; inset: 0; z-index: -2;
  background:
    radial-gradient(60% 55% at 78% 34%, rgba(176,112,14,.30), transparent 70%),
    linear-gradient(94deg,
      rgba(15,16,32,.94) 0%, rgba(19,21,44,.78) 34%,
      rgba(26,28,51,.34) 62%, rgba(15,16,32,.52) 100%),
    linear-gradient(0deg,
      rgba(78,15,28,.80) 0%, rgba(60,14,26,.34) 26%, transparent 58%);
}
/* Grain over the photograph. Same tooth as the coloured bands. */
.hero::after {
  content: '';
  position: absolute; inset: 0; z-index: -1;
  pointer-events: none; opacity: .26;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='3'/%3E%3C/filter%3E%3Crect width='140' height='140' filter='url(%23n)' opacity='.42'/%3E%3C/svg%3E");
}

.hero__grid { display: block; width: 100%; }
.hero__inner { position: relative; z-index: 1; max-width: 64rem; color: #fff; }
.hero__inner .kicker { color: var(--gold); }
.hero__figure, .hero__foot, .hero__note { display: none; }

/* The stacked triad. Three short lines, the middle one gold. Sized so the
   longest of the three still sits on one line inside .hero__inner. */
.hero__title {
  margin-top: var(--s-5);
  font-size: clamp(2.6rem, 7.6vw, 8.2rem);
  line-height: 0.86;
  letter-spacing: -0.045em;
  font-variation-settings: 'SOFT' 18, 'WONK' 0, 'opsz' 144;
  color: #fff;
  text-wrap: nowrap;
  /* The optical left edge of a cap A sits inside its glyph box; without this
     the headline looks indented against the kicker rule above it. */
  margin-left: -0.055em;
}
/* Each line gets a clip so its rise comes out of a hard edge rather than out
   of thin air. JS adds .is-lit; if JS never runs the :not() default has them
   already up, so the headline can never be stuck invisible. */
.hero__title span {
  display: block;
  overflow: hidden;
  padding-bottom: 0.06em;   /* descenders, or the clip crops the g and y */
}
.hero__title span > i {
  display: block;
  font-style: inherit;
  transform: translateY(0);
}
.hero.is-armed .hero__title span > i {
  transform: translateY(105%);
  transition: transform 620ms var(--e-out);
}
.hero.is-lit .hero__title span > i { transform: translateY(0); }
.hero.is-lit .hero__title span:nth-child(2) > i { transition-delay: 90ms; }
.hero.is-lit .hero__title span:nth-child(3) > i { transition-delay: 180ms; }
@media (prefers-reduced-motion: reduce) {
  .hero.is-armed .hero__title span > i { transform: none; transition: none; }
}
.hero__title .hot, .hero__title .cool, .hero__title em { color: var(--gold); font-style: normal; }

.hero__lede {
  margin-top: var(--s-5);
  max-width: 46ch;
  font-size: var(--t-md);
  color: rgba(255,255,255,.86);
  line-height: 1.6;
}

/* A scroll cue, because a 100svh hero with the fold cutting cleanly under the
   buttons gives a visitor no evidence there is a page below it. The rule runs
   down and repeats — the one looping animation on the site. */
.hero__scroll {
  position: absolute; z-index: 2;
  left: 50%; bottom: clamp(1rem, 3vh, 2rem);
  transform: translateX(-50%);
  display: flex; flex-direction: column; align-items: center; gap: 0.6rem;
  font-size: var(--t-xs); font-weight: 600;
  letter-spacing: .16em; text-transform: uppercase;
  color: rgba(255,255,255,.62);
  transition: color var(--d-base) var(--e-out);
}
.hero__scroll:hover { color: var(--gold); }
.hero__scroll-line {
  position: relative;
  width: 1px; height: 46px;
  background: rgba(255,255,255,.22);
  overflow: hidden;
}
.hero__scroll-line::after {
  content: '';
  position: absolute; inset-inline: 0; top: 0; height: 42%;
  background: var(--gold);
  animation: scrollCue 2.4s var(--e-soft) infinite;
}
@keyframes scrollCue {
  0%       { transform: translateY(-105%); }
  55%,100% { transform: translateY(240%); }
}
@media (prefers-reduced-motion: reduce) { .hero__scroll-line::after { animation: none; } }
/* Below the fold on a short phone the cue would sit on top of the pills. */
@media (max-height: 720px), (max-width: 640px) { .hero__scroll { display: none; } }

.hero__search {
  margin-top: var(--s-6);
  max-width: 560px;
  background: rgba(255,255,255,.96);
  border-color: transparent;
  box-shadow: var(--shadow-4);
}
.hero__search-go { margin-right: 0.4rem; flex: none; }

.hero__cta { display: flex; flex-wrap: wrap; gap: var(--s-3); margin-top: var(--s-6); }

.hero__quick { display: flex; flex-wrap: wrap; gap: 0.5rem; margin-top: var(--s-5); }
.hero__pill {
  display: inline-flex; align-items: center; gap: 0.5rem;
  min-height: 38px;
  padding: 0.35rem 0.9rem;
  border: 1px solid rgba(255,255,255,.3);
  border-radius: var(--r-full);
  background: rgba(255,255,255,.1);
  backdrop-filter: blur(8px); -webkit-backdrop-filter: blur(8px);
  font-size: var(--t-xs); font-weight: 600;
  color: #fff;
  transition: background var(--d-fast) var(--e-out), color var(--d-fast) var(--e-out);
}
.hero__pill:hover { background: #fff; color: var(--ink); }
.hero__pill-dot { width: 6px; height: 6px; border-radius: 50%; background: #6EE7C4; flex: none; }

@media (max-width: 720px) { .hero__search-go { display: none; } }
@media (max-width: 560px) { .hero__title { text-wrap: balance; } }

/* ============================================================== FACTS ====
   Four enormous gold numerals, now on the ROOF GREEN band — the fascia colour
   off the building — instead of on black. Black was the safe choice and it
   made the loudest section on the page also the most anonymous one. See .stat
   in ui.css for the numerals, and countUp() in app.js for the count.
   ======================================================================== */
.pulse {
  background: linear-gradient(160deg, var(--roof-band), var(--roof-band-2));
  padding-block: clamp(4rem, 7.5vw, 7rem);
}
.facts { display: grid; grid-template-columns: repeat(4, 1fr); gap: var(--s-6) var(--s-5); }
/* A hairline between the figures. Four numbers floating in a green field read
   as four unrelated facts; ruled off, they read as one set. */
.facts > * + * { border-left: 1px solid rgba(255,255,255,.14); padding-left: var(--s-5); }
@media (max-width: 700px) {
  .facts { grid-template-columns: repeat(2, 1fr); }
  .facts > :nth-child(odd) { border-left: 0; padding-left: 0; }
}

/* ============================================================== DOORS ====
   Four photographs of the building, each one a door into a section.

   Jul 31 2026 — a bento, not a 2x2. Four equal rectangles tell a visitor that
   the shop directory and the parking notes are worth the same glance, which is
   false: the directory is what nearly everyone came for. So the directory runs
   at four times the area of its neighbours, "Plan your visit" takes the full
   width as a footer bar, and the eye now has somewhere to land first.
   ======================================================================== */
.doors {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  grid-auto-rows: minmax(min(30vw, 232px), auto);
  gap: var(--s-4);
}
.doors > :nth-child(1) { grid-column: span 2; grid-row: span 2; }
.doors > :nth-child(4) { grid-column: 1 / -1; min-height: 0; }
/* The wide one is a bar, not a picture — its photograph has no room to be one. */
.doors > :nth-child(4) { grid-row: span 1; }

@media (max-width: 900px) {
  .doors { grid-template-columns: repeat(2, 1fr); }
  .doors > :nth-child(1) { grid-column: 1 / -1; grid-row: span 1; }
  .doors > :nth-child(4) { grid-column: 1 / -1; }
}
@media (max-width: 560px) {
  .doors { grid-template-columns: 1fr; grid-auto-rows: minmax(200px, auto); }
  .doors > :nth-child(1) { grid-row: span 1; }
}

.door {
  position: relative;
  display: flex; flex-direction: column; justify-content: flex-end;
  gap: 0.3rem;
  padding: var(--s-6);
  border-radius: var(--r-lg);
  overflow: hidden;
  isolation: isolate;
  color: #fff;
  background: var(--ink-band);
  box-shadow: var(--shadow-2);
  transition: box-shadow var(--d-base) var(--e-out), transform var(--d-base) var(--e-out);
}
.door__img {
  position: absolute; inset: 0; z-index: -2;
  width: 100%; height: 100%;
  object-fit: cover;
  transition: transform 900ms var(--e-out);
}
.door::before {
  content: ''; position: absolute; inset: 0; z-index: -1;
  background: linear-gradient(180deg, rgba(12,11,9,.12) 28%, rgba(12,11,9,.86) 100%);
}
/* The gold arrow in the bottom-right corner — the reference cards' one piece
   of chrome, and the thing that tells you the whole photograph is a link. */
.door::after {
  content: '';
  position: absolute; right: var(--s-6); bottom: var(--s-6);
  width: 20px; height: 20px;
  background: var(--gold);
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M7 17 17 7'/%3E%3Cpath d='M8 7h9v9'/%3E%3C/svg%3E") center / contain no-repeat;
          mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M7 17 17 7'/%3E%3Cpath d='M8 7h9v9'/%3E%3C/svg%3E") center / contain no-repeat;
  transition: transform var(--d-base) var(--e-out);
}
.door:hover, .door:focus-visible { box-shadow: var(--shadow-lift); transform: translateY(-6px); }
.door:hover .door__img, .door:focus-visible .door__img { transform: scale(1.09); }
.door:hover::after, .door:focus-visible::after { transform: translate(4px, -4px); }
/* The gradient deepens and warms toward the mall's wine on hover, so the card
   reacts in the brand's colour rather than just getting slightly darker. */
.door:hover::before, .door:focus-visible::before {
  background: linear-gradient(180deg, rgba(12,11,9,.10) 22%, rgba(78,15,28,.62) 74%, rgba(40,8,15,.92) 100%);
}
.door::before { transition: background var(--d-slow) var(--e-out); }

.door__num, .door__icon { display: none; }

.door__title {
  font-family: var(--display);
  font-size: clamp(1.7rem, 2.6vw, 2.4rem);
  font-weight: 600; line-height: 1.02;
  letter-spacing: -0.028em;
  font-variation-settings: 'SOFT' 24, 'WONK' 0, 'opsz' 144;
  color: #fff;
}
/* The hero tile of the bento carries a hero-sized title. Scoped to the wide
   breakpoint because at 2-up and 1-up it is no longer the biggest card. */
@media (min-width: 901px) {
  .doors > :nth-child(1) .door__title { font-size: clamp(2.4rem, 3.6vw, 3.6rem); }
  .doors > :nth-child(1) .door__text  { font-size: var(--t-base); max-width: 40ch; }
  /* The full-width bar reads as a line, not a stacked card. */
  .doors > :nth-child(4) {
    flex-direction: row; align-items: flex-end; flex-wrap: wrap;
    gap: 0.3rem var(--s-5);
    padding-right: calc(var(--s-6) + 2.5rem);
  }
  .doors > :nth-child(4) .door__text { padding-bottom: 0.3rem; }
  .doors > :nth-child(4) .door__meta { margin-top: 0; padding-bottom: 0.45rem; }
}
/* The visit card's photograph is the only portrait one (1024x1536), and in a
   wide bar `cover` centres it on empty sky. 72% puts the crop on the ENTER /
   Salida lanes and the bollards — the part of a car park photograph that
   actually says "this is where you drive in". */
.doors > :nth-child(4) .door__img { object-position: center 72%; }
.door__text { max-width: 34ch; font-size: var(--t-sm); color: rgba(255,255,255,.82); line-height: 1.5; }
.door__meta {
  margin-top: 0.5rem;
  font-size: var(--t-xs); font-weight: 700;
  letter-spacing: .08em; text-transform: uppercase;
  color: var(--gold);
  border: 0; padding: 0;
}

/* ======================================================= RETIRED BLOCKS ====
   The sticky scroll-driven "floor by floor" stage, and the CSS-drawn night
   playground with its animated swings and fairy lights. Both were the kind of
   thing that impresses for four seconds and then stands between a visitor and
   what they came for. Hidden rather than deleted so no page 404s a class.
   ======================================================================== */
.day, .welcome { display: none !important; }

/* ========================================================== AMENITIES ==== */
.amen { background: var(--paper-2); border-block: 1px solid var(--line); }
/* Three, not four. Each of these is an icon plus a heading plus two or three
   lines of text; at four across on a 1290px shell the text column is about
   28 characters wide, so "with the ticket stamped by / the attendant" breaks
   over four lines and the row's height is set by whichever one wraps worst. */
.amen-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--s-6) var(--s-5); }
@media (max-width: 1080px) { .amen-grid { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 560px)  { .amen-grid { grid-template-columns: 1fr; } }

/* ============================================================ CLOSING ==== */
.closing { text-align: center; overflow: hidden; }
.closing__inner { position: relative; z-index: 1; }
.closing__title { font-size: var(--t-xl); }
.closing__lede { margin-inline: auto; margin-top: var(--s-5); }
.closing__cta { justify-content: center; margin-top: var(--s-6); }

/* ========================================================== CARD GRID ==== */
/* Shop cards carry a 5:4 mark panel, so the column count is what sets how big
   a shopfront reads. Two across on a phone rather than one: a single card per
   row turns twenty-five shops into a mile of scrolling, and at 165px the panel
   and the two-line blurb both still hold. */
.card-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: var(--s-4); }
@media (max-width: 1180px) { .card-grid { grid-template-columns: repeat(3, 1fr); } }
@media (max-width: 860px)  { .card-grid { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 520px)  { .card-grid { gap: var(--s-3); } }

.card-grid--3 { grid-template-columns: repeat(3, 1fr); }
@media (max-width: 940px) { .card-grid--3 { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 560px) { .card-grid--3 { grid-template-columns: 1fr; } }

/* ============================================================== HOURS ==== */
.hours { display: flex; flex-direction: column; }
.hours__row {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: var(--s-4);
  padding: 0.62rem 0;
  border-bottom: 1px solid var(--line);
  font-size: var(--t-sm);
}
.hours__row dt { color: var(--fg-dim); }
.hours__row dd { color: var(--fg); font-weight: 600; }
.hours__row.is-today dt, .hours__row.is-today dd { color: var(--roof); }
.hours__today {
  display: inline-block; margin-left: 0.5rem;
  padding: 0.05rem 0.4rem;
  border: 1px solid currentColor; border-radius: var(--r-sm);
  font-size: 0.6rem; font-weight: 700; letter-spacing: 0.1em; text-transform: uppercase;
  vertical-align: 1px;
}

/* ========================================================== DIRECTORY ==== */
.dir-toolbar {
  position: sticky; top: var(--header-h);
  z-index: var(--z-sticky);
  padding-block: var(--s-4);
  background: color-mix(in srgb, var(--paper) 94%, transparent);
  backdrop-filter: blur(16px);
  -webkit-backdrop-filter: blur(16px);
  border-bottom: 1px solid var(--line);
}
.dir-toolbar__row { display: flex; gap: var(--s-3); align-items: center; }
.dir-toolbar__row + .dir-toolbar__row { margin-top: var(--s-3); }
.dir-toolbar .search { flex: 1; min-width: 0; }

/* On a phone the search box, the open-now filter and the grid/list toggle
   were sharing one row, which left about 120px for the input — you could see
   "Search sh…" and nothing you typed. Search takes the full width; the
   controls drop underneath it. */
@media (max-width: 640px) {
  .dir-toolbar__row { flex-wrap: wrap; }
  .dir-toolbar .search { flex: 1 0 100%; }
  /* And it stops being sticky. Stacked, the toolbar is about 200px tall; under
     a 74px header that is a third of a phone screen pinned open for the whole
     page, with the shops scrolling through the gap underneath. You filter once
     and then browse — so it scrolls away with everything else. */
  .dir-toolbar { position: static; }
}

/* The overflow-x here only works if the strip is allowed to be narrower than
   its contents. As a flex child its default min-width is auto — the width of
   all ten chips — so instead of scrolling inside itself it pushed the whole
   page sideways: 636px of document on a 390px phone. */
.dir-filters {
  display: flex; gap: 0.45rem;
  flex: 1 1 auto;
  min-width: 0;
  overflow-x: auto;
  padding-bottom: 2px;
  scrollbar-width: none;
  -ms-overflow-style: none;
}
.dir-filters > .chip { flex: none; }
.dir-filters::-webkit-scrollbar { display: none; }

.dir-meta {
  display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between;
  gap: var(--s-3);
  padding-block: var(--s-5);
  font-size: var(--t-sm); color: var(--fg-dim);
}
.dir-meta__count b { color: var(--fg); font-variant-numeric: tabular-nums; }

.view-toggle { display: flex; gap: 2px; padding: 3px; border: 1px solid var(--line-2); border-radius: var(--r-full); }
.view-toggle button {
  width: 38px; height: 32px;
  display: grid; place-items: center;
  border-radius: var(--r-full);
  color: var(--fg-mute);
  transition: all var(--d-fast) var(--e-out);
}
.view-toggle button svg { width: 16px; height: 16px; }
.view-toggle button[aria-pressed="true"] { background: var(--ink); color: var(--paper); }

/* A–Z rail */
/* 30px squares were under the 44px minimum on a phone, and the letters sit
   side by side — so a thumb hitting "M" got "N" about as often. */
.az-rail { display: flex; flex-wrap: wrap; gap: 2px; }
.az-rail button {
  min-width: 34px; height: 34px;
  padding: 0 0.3rem;
  border-radius: var(--r-sm);
  font-size: var(--t-xs); font-weight: 700;
  color: var(--fg-mute);
  transition: all var(--d-fast) var(--e-out);
}
@media (max-width: 760px) {
  .az-rail { gap: 4px; }
  .az-rail button { min-width: 44px; height: 44px; font-size: var(--t-sm); }
  /* Twelve of the twenty-six letters have no shop behind them. At 44px thumb
     size that is four rows of rail on a phone, most of it greyed out, sitting
     between the filters and the shops. The dead letters come out; what is left
     is a jump list of the letters that actually exist. */
  .az-rail button:disabled { display: none; }
}
.az-rail button:hover:not(:disabled) { background: var(--paper-4); color: var(--fg); }
.az-rail button:disabled { opacity: .22; cursor: not-allowed; }
.az-rail button.is-on { background: var(--ink-band); color: #fff; }

/* List view */
.dir-list { border-top: 1px solid var(--line); }
.dir-row {
  position: relative;
  display: grid;
  /* minmax(0,...) not plain fr: a 1fr track floors at min-content, and the
     blurb below is nowrap, so its min-content is the whole sentence. That
     pushed the row to 636px inside a 390px phone and scrolled the page
     sideways. */
  grid-template-columns: 46px minmax(0, 1.6fr) minmax(0, 1fr) minmax(0, 0.9fr) auto;
  gap: var(--s-4);
  align-items: center;
  padding: var(--s-4) var(--s-3);
  border-bottom: 1px solid var(--line);
  transition: background var(--d-fast) var(--e-out), padding-left var(--d-base) var(--e-out);
}
.dir-row > * { min-width: 0; }
.dir-row:hover { background: var(--paper-2); }
/* Both are spans inside a span, so without this the name and the blurb run
   together on one line: "Anand's Gold & Diamond Collection Ltd — diamonds…". */
.dir-row__name { display: block; font-family: var(--sans); font-size: var(--t-md); font-weight: 650; letter-spacing: -0.015em; }
.dir-row__sub {
  display: block;
  font-size: var(--t-xs); color: var(--fg-mute); margin-top: 0.15rem;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.dir-row__cat { font-size: var(--t-sm); color: var(--fg-dim); }
.dir-row__unit { font-size: var(--t-sm); color: var(--fg-mute); font-variant-numeric: tabular-nums; }
.dir-row__go { color: var(--fg-mute); }
.dir-row__go svg { width: 16px; height: 16px; transition: transform var(--d-base) var(--e-out); }
.dir-row:hover .dir-row__go { color: var(--roof); }
.dir-row:hover .dir-row__go svg { transform: translateX(3px); }
@media (max-width: 860px) {
  .dir-row { grid-template-columns: 42px minmax(0, 1fr) auto; }
  .dir-row__cat, .dir-row__unit { display: none; }
}

/* Section letter heading in A–Z mode */
.az-head {
  display: flex; align-items: center; gap: var(--s-4);
  padding-top: var(--s-6); padding-bottom: var(--s-2);
  font-family: var(--sans);
  font-size: var(--t-md); font-weight: 700;
  color: var(--roof);
}
.az-head::after { content: ''; flex: 1; height: 1px; background: var(--line); }

/* ============================================================== STORE ==== */
.store-hero { display: grid; grid-template-columns: 1fr 0.72fr; gap: clamp(2rem,5vw,4rem); align-items: start; }
@media (max-width: 940px) { .store-hero { grid-template-columns: 1fr; } }
.store-hero__title { margin-top: var(--s-2); font-size: var(--t-xl); }
.store-hero__meta { display: flex; flex-wrap: wrap; gap: var(--s-3); margin-top: var(--s-5); }
.store-panel {
  padding: var(--s-6);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  background: var(--surface);
}
.store-panel + .store-panel { margin-top: var(--s-4); }
.store-panel__head {
  font-family: var(--sans);
  font-size: var(--t-sm); font-weight: 700;
  letter-spacing: 0; text-transform: none;
  color: var(--fg-mute);
  margin-bottom: var(--s-4);
}
.store-body { font-size: var(--t-md); color: var(--ink-soft); line-height: 1.7; max-width: 62ch; }
.store-body + .store-body { margin-top: var(--s-4); }

.kv { display: flex; align-items: baseline; justify-content: space-between; gap: var(--s-4); padding: 0.55rem 0; border-bottom: 1px solid var(--line); font-size: var(--t-sm); }
.kv:last-child { border-bottom: 0; }
.kv dt { color: var(--fg-mute); }
.kv dd { font-weight: 600; text-align: right; }

/* ======================================================= FLOOR GUIDE ===== */
/* No stage, no drawing. A picker, then the floor. See map.js for why the two
   previous versions of this page — a fake plan and then a cross-section of the
   building — were both thrown away. */

.floor-picker {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: var(--s-3);
}
@media (max-width: 800px) { .floor-picker { grid-template-columns: repeat(2, 1fr); } }

.floor-pick {
  display: flex; flex-direction: column; align-items: flex-start; gap: .15rem;
  min-height: 88px;
  padding: var(--s-4);
  text-align: left;
  border: 1px solid var(--line-2);
  border-radius: var(--r-lg);
  background: var(--surface);
  transition: border-color var(--d-fast) var(--e-out),
              background var(--d-fast) var(--e-out),
              color var(--d-fast) var(--e-out),
              transform var(--d-fast) var(--e-out);
}
.floor-pick:hover { border-color: var(--roof); transform: translateY(-2px); }
.floor-pick__short {
  font-family: var(--display);
  font-size: 1rem; font-weight: 600;
  color: var(--poui);
  line-height: 1;
}
.floor-pick__name {
  font-size: var(--t-md); font-weight: 650;
  letter-spacing: -0.015em;
  margin-top: .35rem;
}
.floor-pick__count { font-size: var(--t-xs); color: var(--fg-mute); }

.floor-pick[aria-pressed="true"] {
  background: var(--ink-band);
  border-color: var(--ink-band);
  color: var(--paper);
}
.floor-pick[aria-pressed="true"] .floor-pick__short { color: var(--gold); }
.floor-pick[aria-pressed="true"] .floor-pick__count { color: rgba(255,255,255,.62); }

.search--wide { margin-top: var(--s-4); max-width: 520px; }

/* ------------------------------------------------------------- the floor */
.floor-head { margin-top: var(--s-6); padding-bottom: var(--s-4); border-bottom: 1px solid var(--line); }
.floor-head__title { font-size: var(--t-xl); letter-spacing: -0.02em; }
.floor-head__desc { margin-top: .5rem; color: var(--fg-dim); max-width: 62ch; line-height: 1.6; }

.floor-groups { display: flex; flex-direction: column; gap: var(--s-6); margin-top: var(--s-5); }

.floor-group__head {
  display: flex; align-items: center; gap: .55rem;
  font-family: var(--sans);
  font-size: .72rem; font-weight: 700;
  letter-spacing: .12em; text-transform: uppercase;
  color: var(--fg-mute);
  padding-bottom: .6rem;
  border-bottom: 1px solid var(--line);
}
.floor-group__icon { display: inline-flex; color: var(--poui); }
.floor-group__icon svg { width: 15px; height: 15px; }
.floor-group__n {
  margin-left: auto;
  font-size: .7rem; letter-spacing: .04em;
  color: var(--fg-mute);
}

.floor-list { list-style: none; margin: 0; padding: 0; }
.floor-list li + li { border-top: 1px solid var(--line); }

.floor-item {
  display: grid;
  grid-template-columns: 42px minmax(0, 1fr) auto auto 16px;
  align-items: center;
  gap: var(--s-4);
  padding: var(--s-4) .35rem;
  color: inherit;
  transition: background var(--d-fast) var(--e-out);
}
.floor-item:hover { background: var(--paper-2); }
.floor-item__text { min-width: 0; }
.floor-item__name {
  display: block;
  font-size: var(--t-md); font-weight: 650; letter-spacing: -0.015em;
}
.floor-item__sub {
  display: block;
  font-size: var(--t-xs); color: var(--fg-mute);
  margin-top: .15rem;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.floor-item__unit {
  font-size: var(--t-xs); font-weight: 600;
  padding: .22rem .55rem;
  border-radius: var(--r-full);
  background: var(--paper-3);
  color: var(--fg-dim);
  white-space: nowrap;
}
.floor-item__go { display: inline-flex; color: var(--fg-mute); }
.floor-item__go svg { width: 16px; height: 16px; }
.floor-item:hover .floor-item__go { color: var(--poui); }

.floor-empty { margin-top: var(--s-5); color: var(--fg-mute); line-height: 1.7; }
.floor-empty a { color: var(--poui); text-decoration: underline; }

/* On a phone the blurb and the status pill are both losing the fight for the
   row, so the row becomes two lines and the blurb steps out. */
@media (max-width: 720px) {
  .floor-item { grid-template-columns: 42px minmax(0, 1fr) auto; gap: var(--s-3); }
  .floor-item__sub { display: none; }
  .floor-item__go { display: none; }
  .floor-item__unit { grid-column: 2; grid-row: 2; justify-self: start; }
  .floor-item .status { grid-column: 3; grid-row: 1; }
}

/* --------------------------------------------------------- getting around */
.around {
  padding: var(--s-6) clamp(1.25rem, 3vw, 2.5rem);
  border: 1px solid var(--line-2);
  border-radius: var(--r-lg);
  background: var(--paper-2);
}
.around__title { font-size: var(--t-xl); letter-spacing: -0.02em; }
.around__list {
  list-style: none; margin: var(--s-5) 0 0; padding: 0;
  display: grid; gap: var(--s-5);
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
}
.around__item h3 {
  font-size: var(--t-sm); font-weight: 700;
  letter-spacing: .04em;
  margin-bottom: .4rem;
}
.around__item p { font-size: var(--t-sm); color: var(--fg-dim); line-height: 1.65; }
.around__item a { color: var(--poui); text-decoration: underline; text-underline-offset: 2px; }

/* ============================================================= DINING ==== */
.menu-strip {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: var(--s-4);
  padding: var(--s-6);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  background: var(--surface);
}
.menu-strip__item { text-align: center; }
.menu-strip__val { font-family: var(--display); font-size: var(--t-lg); color: var(--poui); font-variation-settings: 'SOFT' 26,'WONK' 1; }
.menu-strip__lab { margin-top: 0.3rem; font-size: var(--t-xs); color: var(--fg-mute); letter-spacing: 0.1em; text-transform: uppercase; font-weight: 600; }

/* ============================================================ LEASING ==== */
.lease-grid { display: grid; grid-template-columns: 1fr 0.9fr; gap: clamp(2rem,5vw,4rem); align-items: start; }
@media (max-width: 940px) { .lease-grid { grid-template-columns: 1fr; } }
.lease-form { padding: var(--s-6); border: 1px solid var(--line-2); border-radius: var(--r-lg); background: var(--surface); display: flex; flex-direction: column; gap: var(--s-4); }
.form-row { display: grid; grid-template-columns: 1fr 1fr; gap: var(--s-4); }
@media (max-width: 620px) { .form-row { grid-template-columns: 1fr; } }

/* ============================================================== ABOUT ==== */
.timeline { border-left: 1px solid var(--line); padding-left: var(--s-6); }
.tl-item { position: relative; padding-bottom: var(--s-7); }
.tl-item::before {
  content: ''; position: absolute; left: calc(var(--s-6) * -1 - 5px); top: 0.55rem;
  width: 9px; height: 9px; border-radius: 50%;
  background: var(--paper); border: 1px solid var(--poui);
}
.tl-year { font-family: var(--display); font-size: var(--t-lg); color: var(--poui); font-variation-settings: 'SOFT' 26,'WONK' 1; line-height: 1; }
.tl-title { margin-top: var(--s-3); font-size: var(--t-md); font-weight: 600; }
.tl-text { margin-top: var(--s-2); color: var(--fg-dim); font-size: var(--t-sm); max-width: 58ch; line-height: 1.65; }

/* ============================================================ CONTACT ==== */
.contact-grid { display: grid; grid-template-columns: 0.9fr 1fr; gap: clamp(2rem,5vw,4rem); align-items: start; }
@media (max-width: 940px) { .contact-grid { grid-template-columns: 1fr; } }
.contact-card {
  display: flex; gap: var(--s-4); align-items: flex-start;
  padding: var(--s-5);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  transition: border-color var(--d-base) var(--e-out), transform var(--d-base) var(--e-out);
}
.contact-card:hover { border-color: var(--line-2); transform: translateX(4px); }
.contact-card__icon { width: 40px; height: 40px; flex: none; display: grid; place-items: center; border-radius: var(--r-sm); border: 1px solid var(--line-2); color: var(--poui); }
.contact-card__icon svg { width: 18px; height: 18px; }
.contact-card > span:last-child, .contact-card > div { min-width: 0; }
.contact-card__label { display: block; font-size: var(--t-xs); color: var(--fg-mute); letter-spacing: 0.12em; text-transform: uppercase; font-weight: 600; }
/* break-word, not anywhere: the values now carry <wbr> at the @ and the dots,
   and `anywhere` overrides those preferred points and snaps mid-word regardless. */
.contact-card__value { display: block; margin-top: 0.25rem; font-size: var(--t-base); font-weight: 600; line-height: 1.35; overflow-wrap: break-word; }
.contact-card__note { display: block; margin-top: 0.35rem; font-size: var(--t-xs); color: var(--fg-mute); line-height: 1.5; }

/* ====================================================== SPLIT PAGE HEAD === */
/* Asymmetric header: copy left, a live panel right. Breaks the every-section-
   looks-the-same rhythm that makes template sites feel machine-made. */
.split-head {
  display: grid;
  grid-template-columns: 1.35fr 0.65fr;
  gap: clamp(2rem, 5vw, 4rem);
  align-items: end;
}
@media (max-width: 900px) { .split-head { grid-template-columns: 1fr; } }
.split-head__side { padding-bottom: .5rem; }

/* ====================================================== PULL QUOTE BAND === */
.headline-band {
  position: relative;
  padding: clamp(2rem, 5vw, 3.5rem) clamp(1.5rem, 5vw, 4rem);
  border: 1px solid var(--line-2);
  border-radius: var(--r-xl);
  background:
    radial-gradient(ellipse 70% 120% at 15% 0%, rgba(44,106,92,.07), transparent 60%),
    var(--paper-2);
  overflow: hidden;
}
.headline-band::before { display: none; }
.pullquote {
  position: relative;
  margin-top: var(--s-4);
  font-family: var(--display);
  font-size: clamp(1.3rem, 2.4vw, 2rem);
  font-weight: 400;
  line-height: 1.28;
  letter-spacing: -0.02em;
  font-variation-settings: 'SOFT' 20, 'WONK' 0, 'opsz' 100;
  max-width: 34ch;
  text-wrap: balance;
}
.pullquote__cite {
  margin-top: var(--s-5);
  font-size: var(--t-sm);
  color: var(--fg-mute);
  max-width: 56ch;
}
.pullquote__cite a { color: var(--roof); text-decoration: underline; text-underline-offset: 2px; }

/* =========================================================== MEDIA GRID === */
.media-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
  gap: var(--s-5);
}
.media-grid__note {
  grid-column: 1 / -1;
  margin-top: var(--s-2);
  font-size: var(--t-xs);
  color: var(--fg-mute);
  line-height: 1.65;
  max-width: 78ch;
}

.media-card {
  margin: 0;
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  background: var(--surface);
  overflow: hidden;
  transition: border-color var(--d-base) var(--e-out), transform var(--d-base) var(--e-out);
}
.media-card:hover { border-color: var(--line-2); transform: translateY(-3px); }

.media-card__play, .media-card__link {
  display: block; width: 100%;
  position: relative;
  padding: 0; border: 0;
  cursor: pointer;
  text-align: left;
}
.media-card__thumb {
  position: relative;
  display: grid; place-items: center;
  aspect-ratio: 16 / 9;
  background: var(--paper-3);
  border-bottom: 1px solid var(--line);
  overflow: hidden;
}
/* These three tiles have no thumbnail — the photographs live on Flickr and
   Instagram and are not ours to copy — so the tile has to look like a door on
   purpose rather than like an image that failed to load. A 20px grey glyph
   floating in a near-white 16:9 box looked like the latter. Same treatment as
   a shop card's mark panel: a tint of the brand colour, and a mark big enough
   to be the subject of the tile. */
.media-card__thumb--link {
  background: linear-gradient(160deg,
    color-mix(in srgb, var(--roof) 10%, var(--paper)),
    color-mix(in srgb, var(--roof) 3%, var(--paper)));
}
.media-card__glow { display: none; }
.media-card__icon {
  position: relative;
  width: 64px; height: 64px;
  color: var(--roof);
  padding: 18px;
  border: 1px solid color-mix(in srgb, var(--roof) 28%, transparent);
  border-radius: 50%;
  background: #fff;
  transition: background var(--d-base) var(--e-out), color var(--d-base) var(--e-out);
}
.media-card:hover .media-card__icon { background: var(--roof); color: #fff; border-color: var(--roof); }

.media-card__badge {
  position: absolute; left: var(--s-3); top: var(--s-3);
  padding: .2rem .55rem;
  border: 1px solid var(--line-2);
  border-radius: var(--r-sm);
  background: rgba(10,8,6,.7);
  font-size: 0.62rem; font-weight: 700;
  letter-spacing: .1em; text-transform: uppercase;
  color: var(--ink-dim);
}
.media-card__frame { aspect-ratio: 16 / 9; border-bottom: 1px solid var(--line); }
.media-card__frame iframe { width: 100%; height: 100%; border: 0; display: block; }

.media-card__cap { padding: var(--s-5); }
.media-card__title {
  font-family: var(--sans); font-size: var(--t-md); font-weight: 650;
  letter-spacing: -0.015em; line-height: 1.25;
}
.media-card__note { margin-top: .6rem; font-size: var(--t-sm); color: var(--fg-dim); line-height: 1.6; }
.media-card__credit { margin-top: .85rem; font-size: var(--t-xs); color: var(--fg-mute); }
.media-card__credit a { color: var(--roof); }
.media-card__credit a:hover { text-decoration: underline; }

/* ======================================================== SOURCE NOTES ==== */
/* Every sourced claim on the site can show where it came from. */
.src-note {
  display: flex; align-items: flex-start; gap: 0.5rem;
  margin-top: var(--s-4);
  font-size: var(--t-xs);
  line-height: 1.55;
  color: var(--fg-mute);
}
.src-note__icon { width: 13px; height: 13px; flex: none; margin-top: 0.28em; color: var(--roof); }

.sourced {
  padding: var(--s-4) var(--s-5);
  border: 1px solid color-mix(in srgb, var(--roof) 28%, transparent);
  border-left: 2px solid var(--roof);
  border-radius: var(--r-sm);
  background: color-mix(in srgb, var(--roof) 6%, transparent);
  font-size: var(--t-sm);
  color: var(--fg-dim);
  line-height: 1.65;
}
.sourced b { color: var(--ink-soft); }
.sourced a { color: var(--roof); text-decoration: underline; text-underline-offset: 2px; }

.source-list { display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); gap: var(--s-3); }
.source-list a {
  display: flex; align-items: center; gap: 0.6rem;
  padding: var(--s-3) var(--s-4);
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  font-size: var(--t-sm);
  color: var(--fg-dim);
  transition: all var(--d-fast) var(--e-out);
}
.source-list a:hover { border-color: var(--roof); color: var(--fg); }
.source-list svg { width: 14px; height: 14px; flex: none; opacity: .7; }

/* ============================================================== NOTES ==== */
/* --plum was never defined anywhere in this stylesheet, so all three of the
   declarations that referenced it were invalid and dropped: the note-band has
   been rendering with no border, no left rule and no tint since it was
   written — a plain grey paragraph that looked like body copy someone had
   forgotten to style. Poui, which is a real token and the right temperature
   for an advisory. */
.note-band {
  padding: var(--s-4) var(--s-5);
  border: 1px solid color-mix(in srgb, var(--poui) 34%, transparent);
  border-left: 2px solid var(--poui);
  border-radius: var(--r-sm);
  background: color-mix(in srgb, var(--poui) 8%, transparent);
  font-size: var(--t-sm);
  color: var(--fg-dim);
}
.note-band b { color: var(--ink-soft); }

/* ============================================================= GALLERY ====
   A full-bleed band of the owner's own photographs of the building. This is
   the section that answers "what does it actually look like" — so it gets the
   darkest ground on the page and the largest frames.
   ======================================================================== */
/* The gallery used to sit on a full-bleed dark green field with white type and
   gold italics — the page went light, dark, light, dark as you scrolled. It is
   the photographs that should carry this section, so they now sit on paper. */
.gallery-band { padding-block: clamp(3rem, 7vw, 5.5rem); }
.gallery-head {
  display: grid;
  grid-template-columns: minmax(0, 1.3fr) minmax(0, 1fr);
  gap: var(--s-5) var(--s-7);
  align-items: end;
  margin-bottom: var(--s-6);
}
@media (max-width: 800px) { .gallery-head { grid-template-columns: 1fr; } }
.gallery-title {
  margin-top: var(--s-2);
  font-size: var(--t-xl);
  line-height: 1.05;
  letter-spacing: -0.025em;
}
.gallery-title em { font-style: normal; color: var(--gold-deep); }
.gallery-note { font-size: var(--t-sm); color: var(--fg-dim); line-height: 1.6; max-width: 46ch; }
.gallery-note a { color: var(--roof); text-decoration: underline; text-underline-offset: 3px; }

/* Three sizes, and the tiling is arithmetic rather than hope.

   The last attempt at a masonry here was abandoned because it left a quarter
   of the final row empty — a hole that looked like a bug — and it was replaced
   by six identical rectangles, which is the safe answer and also the reason
   this section had nothing to look at first. The grid below cannot leave a
   hole, because the spans are chosen to consume the cells exactly:

     4 columns x 3 rows = 12 cells
     photo 1 takes 2x2 = 4, photos 2 and 3 take 1 each, photos 4, 5 and 6
     take 2 each  ->  4 + 1 + 1 + 2 + 2 + 2 = 12.

   It holds at the 2-column breakpoint too (2x2 + 1 + 1 + 2 + 2 + 2 = 12 over
   6 rows). Keyed to nth-child because it is a fixed set of six photographs of
   one building, not a feed — if a seventh is ever added, the spans have to be
   re-derived, and there is no way to write that as a rule that just works. */
.gallery {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  grid-auto-rows: clamp(146px, 14.5vw, 226px);
  gap: var(--s-4);
}
.gallery__item:nth-child(1) { grid-column: span 2; grid-row: span 2; }
.gallery__item:nth-child(4),
.gallery__item:nth-child(5),
.gallery__item:nth-child(6) { grid-column: span 2; }
.gallery__item {
  position: relative;
  margin: 0;
  overflow: hidden;
  border-radius: var(--r-md);
  background: var(--navy);
}
/* The old size modifiers are inert — the nth-child spans above own the layout
   now, and having both would mean two rules fighting over the same photo. */
.gallery__item--tall, .gallery__item--wide { grid-row: auto; grid-column: auto; }
.gallery__item:nth-child(1).gallery__item--tall { grid-column: span 2; grid-row: span 2; }
.gallery__item img {
  width: 100%; height: 100%;
  object-fit: cover;
  transition: transform 700ms var(--e-out);
}
.gallery__item:hover img { transform: scale(1.07); }
.gallery__item figcaption {
  position: absolute; left: 0; right: 0; bottom: 0;
  padding: 1.6rem .95rem .8rem;
  font-size: var(--t-xs);
  color: rgba(255,255,255,.78);
  background: linear-gradient(180deg, transparent, rgba(10,14,26,.86));
  display: flex; flex-direction: column; gap: .1rem;
}
.gallery__item figcaption b {
  font-size: var(--t-sm);
  font-weight: 700;
  color: #fff;
  letter-spacing: -0.01em;
}
@media (max-width: 900px) { .gallery { grid-template-columns: repeat(2, 1fr); grid-auto-rows: clamp(140px, 21vw, 200px); } }
@media (max-width: 520px) {
  .gallery { grid-template-columns: 1fr; grid-auto-rows: clamp(170px, 44vw, 240px); }
  /* On one column a 2-row span is just a taller photo, which is the right
     answer — but EVERY span that asks for 2 columns must be cleared, the
     first photo's included. `grid-template-columns: 1fr` does not cap a grid
     at one column: a `grid-column: span 2` that does not fit makes the
     browser generate an implicit second track, so leaving nth-child(1)'s span
     in place quietly rebuilt the two-column layout underneath the override
     and the whole gallery stayed 2-up on a phone. */
  .gallery__item:nth-child(1),
  .gallery__item:nth-child(1).gallery__item--tall,
  .gallery__item:nth-child(4),
  .gallery__item:nth-child(5),
  .gallery__item:nth-child(6) { grid-column: auto; }
}

/* The video card shows YouTube's own still for that video — a real frame from
   inside the mall — with the play button over it. */
.media-card__still {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  object-fit: cover;
  transition: transform 700ms var(--e-out), filter 400ms var(--e-out);
  filter: saturate(1.05) contrast(1.03);
}
.media-card__play:hover .media-card__still { transform: scale(1.05); filter: saturate(1.12) brightness(1.04); }
/* The play mark sits in a white disc (from the base rule), so painting the
   triangle white too left an empty white circle on the video card — the one
   control on the page that has to look pressable. Ink triangle, white disc. */
.media-card--video .media-card__icon {
  position: relative; z-index: 2;
  color: var(--ink);
  border-color: transparent;
  filter: drop-shadow(0 2px 10px rgba(0,0,0,.45));
}
.media-card--video .media-card__play:hover .media-card__icon {
  background: var(--roof); color: #fff;
}
.media-card--video .media-card__thumb::after {
  content: ''; position: absolute; inset: 0; z-index: 1;
  background: linear-gradient(180deg, rgba(12,16,32,.12), rgba(12,16,32,.5));
}

/* Link cards (Instagram, Facebook, Flickr) can't legally carry a thumbnail of
   someone else's photo, so instead of a blank panel they get a brand field and
   a large mark — deliberate rather than unfinished.

   This block used to say exactly that and then do the opposite: it flattened
   the field to plain --paper-3 and shrank the mark back to a 34px grey glyph,
   overriding the rule above it. Three of the four cards in the row rendered as
   an empty box with a speck in the middle, which reads as a broken image. */
.media-card__badge { background: rgba(255,255,255,.9); color: var(--ink-dim); }
.media-card--video .media-card__badge { background: rgba(12,16,32,.7); color: #fff; }

/* ========================================================== EXPANSION ====
   The 2014 rebuild that was announced and never happened. Dark navy so it
   reads as an archive spread rather than a sales pitch, with the figures set
   large enough to land and the "it wasn't built" line impossible to miss.
   ======================================================================== */
/* The 2014 expansion that was announced and never built. It was set as a dark
   navy spread with gold serif italics and uppercase tracked labels — the one
   place left on the site still using the old treatment, which made it look
   like a different website. Same figures, same source, house style. */
/* On the ink band. The billion-dollar rebuild that was announced and never
   delivered is the single most striking thing on Centre City's public record,
   and putting it on cream between two other cream sections buried it. */
.expand-band {
  background: var(--ink-band);
  color: rgba(255,255,255,.78);
  border-block: 0;
  padding-block: clamp(4rem, 8vw, 6.5rem);
}
.expand-band .kicker { color: var(--gold); }
.expand-head {
  display: grid;
  grid-template-columns: minmax(0, 1.1fr) minmax(0, 1fr);
  gap: var(--s-5) var(--s-7);
  align-items: end;
  margin-bottom: var(--s-6);
}
@media (max-width: 860px) { .expand-head { grid-template-columns: 1fr; } }
.expand-title {
  margin-top: var(--s-4);
  font-size: clamp(2rem, 3.4vw, 3.4rem);
  line-height: 1.02;
  letter-spacing: -0.03em;
  color: #fff;
}
.expand-title em { font-style: normal; color: var(--gold); }
.expand-lede { font-size: var(--t-base); line-height: 1.7; color: rgba(255,255,255,.72); }

.expand-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: var(--s-5) var(--s-6);
  margin: 0;
}
@media (max-width: 900px) { .expand-grid { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 520px) { .expand-grid { grid-template-columns: 1fr; } }

.expand-cell { border-top: 1px solid rgba(255,255,255,.18); padding-top: var(--s-4); }
.expand-cell dt {
  font-size: var(--t-sm);
  font-weight: 500;
  letter-spacing: 0;
  text-transform: none;
  color: rgba(255,255,255,.55);
}
/* The money figures in gold serif — they are the story. */
.expand-cell dd {
  margin: .45rem 0 0;
  font-family: var(--display);
  font-size: var(--t-lg);
  font-weight: 600;
  line-height: 1.12;
  letter-spacing: -0.028em;
  font-variation-settings: 'SOFT' 24, 'WONK' 0, 'opsz' 144;
  color: var(--gold);
}

.expand-note {
  margin-top: var(--s-7);
  padding: var(--s-4) var(--s-5);
  border: 1px solid rgba(255,255,255,.16);
  border-left: 2px solid var(--gold);
  border-radius: var(--r-sm);
  background: rgba(255,255,255,.04);
  font-size: var(--t-sm);
  line-height: 1.65;
  color: rgba(255,255,255,.72);
  max-width: 82ch;
}
.expand-note b { color: #fff; }
.expand-note a { color: var(--gold); text-decoration: underline; text-underline-offset: 2px; }

/* ============================================================ WELCOME ====
   The shape both reference malls use to open the page body: a short welcome,
   one oversized number carried inline in the sentence, and a way into the
   longer story.
   ======================================================================== */
.welcome { padding-block: clamp(3rem, 7vw, 5.5rem); }
.welcome__grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.05fr);
  gap: clamp(2rem, 5vw, 4.5rem);
  align-items: center;
}
@media (max-width: 900px) { .welcome__grid { grid-template-columns: 1fr; gap: 2rem; } }
.welcome__title {
  margin-top: var(--s-4);
  font-size: var(--t-xl);
  line-height: 1;
  letter-spacing: -0.03em;
}
.welcome__lede { font-size: var(--t-md); line-height: 1.6; color: var(--fg-dim); }
.welcome__lede b { color: var(--fg); font-weight: 600; }
.welcome__num {
  font-family: var(--display);
  font-size: var(--t-2xl);
  font-weight: 500;
  line-height: .8;
  letter-spacing: -0.04em;
  color: var(--roof);
  font-variant-numeric: tabular-nums;
  margin-right: .12em;
  vertical-align: -.06em;
}

/* ========================================================= SHOP STRIP ====
   Brentwood runs a carousel of tenant logos here. We have no licence to those
   marks, so the strip runs our own drawn emblems instead — same idea, and it
   stays honest about what it is.
   ======================================================================== */
.strip {
  padding-block: clamp(2rem, 5vw, 3.5rem);
  background: var(--paper-2);
  border-block: 1px solid var(--line);
  overflow: hidden;
}
.strip__head {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: var(--s-5); flex-wrap: wrap;
  margin-bottom: var(--s-5);
}
.strip__title {
  font-family: var(--display);
  font-size: var(--t-lg);
  font-weight: 500;
  letter-spacing: -0.025em;
}
.strip__all {
  display: inline-flex; align-items: center; gap: .5rem;
  font-size: var(--t-sm); font-weight: 600;
  color: var(--roof);
}
.strip__all svg { width: 16px; height: 16px; }
.strip__all:hover { color: var(--roof-2); }

.strip__rail { position: relative; display: flex; width: max-content; }
.strip__rail:hover .strip__row { animation-play-state: paused; }
.strip__row {
  display: flex;
  gap: var(--s-4);
  padding-right: var(--s-4);
  animation: stripRun 54s linear infinite;
}
@keyframes stripRun { to { transform: translateX(-100%); } }
@media (prefers-reduced-motion: reduce) {
  .strip__row { animation: none; }
  .strip__rail { overflow-x: auto; }
}

.strip__item {
  display: flex; align-items: center; gap: .8rem;
  flex: none;
  padding: .7rem 1.15rem .7rem .7rem;
  border: 1px solid var(--line);
  border-radius: var(--r-full);
  background: var(--surface);
  transition: border-color var(--d-base) var(--e-out), transform var(--d-base) var(--e-out), box-shadow var(--d-base) var(--e-out);
}
.strip__item:hover {
  border-color: hsl(var(--h) 40% 45% / .5);
  transform: translateY(-2px);
  box-shadow: var(--shadow-2);
}
.strip__name {
  font-size: var(--t-sm);
  font-weight: 600;
  white-space: nowrap;
  letter-spacing: -0.01em;
}
.strip__cat {
  font-size: .68rem;
  font-weight: 600;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--fg-mute);
  white-space: nowrap;
}

/* ======================================================== MEDIA SPLIT ====
   One video with a real still from inside the mall, and beside it the places
   Centre City is published. Previously six identical cards, five of which had
   nothing to put in their picture frame.
   ======================================================================== */
.media-split {
  display: grid;
  grid-template-columns: minmax(0, 1.25fr) minmax(0, 1fr);
  gap: clamp(1.5rem, 4vw, 3rem);
  align-items: start;
}
@media (max-width: 860px) { .media-split { grid-template-columns: 1fr; } }
.media-split__head {
  font-family: var(--sans);
  font-size: var(--t-sm);
  font-weight: 700;
  color: var(--fg-mute);
  margin-bottom: var(--s-3);
}
.media-split .source-list { grid-template-columns: 1fr; }

/* ══════════════════════════════════════════════════════════════════════════
   FULL-BLEED COMPOSITIONS
   Everything below is the structural vocabulary taken off the two reference
   sites and measured in the browser rather than eyeballed. The site had all
   of its content on one flat cream ground; these are the changes of scene.
   ══════════════════════════════════════════════════════════════════════════ */

/* ============================================================== REEL ====
   A photograph that runs the entire width of the window with a caption bar
   across the bottom. Brentwood breaks its home page with one of these — a
   full-width shot of the plaza on a show night — and it does more for the
   feeling of "you are there" than any amount of copy.
   ======================================================================== */
.reel {
  position: relative;
  height: clamp(340px, 58vh, 660px);
  overflow: hidden;
  background: var(--ink-band);
}
/* Absolutely positioned with a vh bleed, not margin-top: -15%. A percentage
   margin resolves against the containing block's WIDTH — on a 1440px-wide,
   522px-tall reel that is -216px against 78px of available headroom, which
   pulled the photograph clean off the top of its own box and left a black
   band across the caption bar. See .hero__bg for why the bleed is in vh. */
.reel__img {
  position: absolute; left: 0; right: 0;
  top: -14vh; height: calc(100% + 28vh);
  width: 100%;
  object-fit: cover;
  object-position: center 68%;   /* the road and the deck, not the sky */
  transform: translate3d(0, var(--parallax-y, 0px), 0);
  will-change: transform;
}
.reel__bar {
  position: absolute; left: 0; right: 0; bottom: 0;
  display: flex; flex-wrap: wrap; align-items: baseline;
  justify-content: space-between; gap: var(--s-4);
  padding: clamp(3rem, 8vw, 5rem) var(--gutter) clamp(1.2rem, 2.5vw, 2rem);
  background: linear-gradient(180deg, transparent, rgba(12,11,9,.9));
}
.reel__label {
  font-family: var(--display);
  font-style: italic;
  font-weight: 600;
  font-size: clamp(1.1rem, 2vw, 1.6rem);
  font-variation-settings: 'SOFT' 30, 'WONK' 0, 'opsz' 40;
  color: #fff;
  display: inline-flex; align-items: center; gap: .85rem;
}
.reel__label::before { content: ''; width: 2.2rem; height: 1px; background: var(--gold); flex: none; }
.reel__credit { font-size: var(--t-xs); color: rgba(255,255,255,.62); }
.reel__credit a { color: rgba(255,255,255,.82); text-decoration: underline; text-underline-offset: 3px; }
.reel__credit a:hover { color: var(--gold); }

/* ============================================================ STORIES ====
   The events, as tall photographs on the wine band with a tag pill in the
   corner. The list-with-a-date-column version was the most newspaper-ish
   thing on the site.
   ======================================================================== */
.stories { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--s-4); }
@media (max-width: 1080px) { .stories { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 540px)  { .stories { grid-template-columns: 1fr; } }

.story {
  position: relative;
  display: flex; flex-direction: column; justify-content: flex-end;
  min-height: clamp(320px, 32vw, 440px);
  padding: var(--s-5);
  border-radius: var(--r-lg);
  overflow: hidden;
  isolation: isolate;
  background: var(--ink-band);
  transition: transform var(--d-base) var(--e-out), box-shadow var(--d-base) var(--e-out);
}
/* Each card is drawn, not photographed: its own accent as a deep field, a
   motif in line-work over the top half, and the type sitting in the dark at
   the bottom where it stays readable. */
.story--gold  { --story-a: 41 82% 60%;  --story-b: 32 44% 12%; }
.story--flame { --story-a: 9  74% 58%;  --story-b: 356 42% 13%; }
.story--sea   { --story-a: 190 58% 56%; --story-b: 199 40% 12%; }
.story {
  background:
    radial-gradient(120% 80% at 78% 4%, hsl(var(--story-a) / .28) 0%, transparent 62%),
    linear-gradient(168deg, hsl(var(--story-b)) 0%, #100E0C 88%);
}
.story__field {
  position: absolute; inset: 0; z-index: -2;
  color: hsl(var(--story-a));
  transition: transform 900ms var(--e-out);
}
.story__field svg { width: 100%; height: 100%; display: block; }
.story::before {
  content: ''; position: absolute; inset: 0; z-index: -1;
  background: linear-gradient(180deg, transparent 34%, rgba(10,9,8,.72) 74%, rgba(10,9,8,.94) 100%);
}
.story:hover { transform: translateY(-4px); box-shadow: var(--shadow-4); }
.story:hover .story__field { transform: translateY(-6px) scale(1.03); }

.story__tag {
  position: absolute; top: var(--s-4); left: var(--s-4);
  padding: .3rem .7rem;
  border-radius: var(--r-full);
  background: rgba(255,255,255,.92);
  font-size: .62rem; font-weight: 700;
  letter-spacing: .1em; text-transform: uppercase;
  color: var(--ink);
}
.story__title {
  font-family: var(--display);
  font-size: clamp(1.5rem, 2.3vw, 2.1rem);
  font-weight: 600; line-height: 1.02;
  letter-spacing: -0.028em;
  font-variation-settings: 'SOFT' 24, 'WONK' 0, 'opsz' 144;
  color: #fff;
}
.story__when {
  margin-top: .6rem;
  font-size: var(--t-xs); font-weight: 700;
  letter-spacing: .06em; text-transform: uppercase;
  color: hsl(var(--story-a, 41 82% 60%));
}
.story__blurb { margin-top: .55rem; font-size: var(--t-sm); line-height: 1.5; color: rgba(255,255,255,.8); }

/* ============================================================ CLOSING ====
   The last thing on the home page before the footer: a photograph of the
   mall filling the window, one line, one gold button.
   ======================================================================== */
.closing {
  position: relative;
  display: grid; place-items: center;
  min-height: clamp(380px, 56vh, 620px);
  padding-block: clamp(4rem, 9vw, 7rem);
  text-align: center;
  overflow: hidden;
  isolation: isolate;
  background: var(--ink-band);
}
.closing__img {
  position: absolute; left: 0; right: 0; z-index: -2;
  top: -14vh; height: calc(100% + 28vh);
  width: 100%; object-fit: cover; object-position: center 55%;
  transform: translate3d(0, var(--parallax-y, 0px), 0);
  will-change: transform;
}
/* Wine up from the floor rather than another flat black scrim — this is the
   last thing before the footer and it should feel like the mall's own colour
   closing over the page. */
.closing::before {
  content: ''; position: absolute; inset: 0; z-index: -1;
  background:
    radial-gradient(70% 60% at 50% 40%, rgba(176,112,14,.20), transparent 68%),
    linear-gradient(180deg, rgba(15,16,32,.78) 0%, rgba(48,12,22,.80) 55%, rgba(78,15,28,.90) 100%);
}
.closing__inner { position: relative; z-index: 1; }
.closing .kicker { color: var(--gold); justify-content: center; }
.closing__title {
  margin-top: var(--s-5);
  font-size: clamp(2.6rem, 6.6vw, 6.2rem);
  line-height: 0.94;
  letter-spacing: -0.038em;
  color: #fff;
}
.closing__title .cool, .closing__title .hot { color: var(--gold); }
.closing__lede { margin-inline: auto; margin-top: var(--s-5); color: rgba(255,255,255,.82); }
.closing__cta { justify-content: center; margin-top: var(--s-6); }

/* ========================================================== PAGE HEAD ====
   Every inner page opens the way the reference directory does: a photograph
   of the building filling the top of the screen, darkened, with the gold
   italic label, the headline stacked large in white, and the lede under it.
   The old split — copy on the left, a framed photo on the right — put a
   picture-frame border round the one thing that should have bled off the edge.
   ======================================================================== */
.page-head {
  position: relative;
  display: flex; align-items: flex-end;
  min-height: clamp(400px, 62vh, 640px);
  padding-top: calc(var(--header-h) + clamp(3rem, 8vh, 6rem));
  padding-bottom: clamp(2.5rem, 6vw, 4.5rem);
  margin-top: calc(var(--header-h) * -1);
  overflow: hidden;
  isolation: isolate;
  border-bottom: 0;
  background: var(--navy-band-2);
  color: rgba(255,255,255,.82);
}
.page-head__bg { position: absolute; inset: 0; z-index: -2; }
.page-head__bg img { width: 100%; height: 100%; object-fit: cover; object-position: center 46%; }
/* The same navy-and-wine wash as the home hero, so an inner page opens in the
   mall's colours rather than in the flat grey-black every other site uses.
   Weaker than the hero's — there is less type over it and it sits under a
   cream page, so it has to hand over rather than dominate. */
.page-head::before {
  content: ''; position: absolute; inset: 0; z-index: -1;
  background:
    radial-gradient(58% 60% at 82% 30%, rgba(176,112,14,.24), transparent 72%),
    linear-gradient(94deg, rgba(15,16,32,.93) 0%, rgba(20,22,46,.72) 44%, rgba(26,28,51,.34) 100%),
    linear-gradient(0deg, rgba(78,15,28,.62) 0%, rgba(50,12,22,.24) 30%, transparent 60%);
}
/* Grain, matching the coloured bands. */
.page-head::after {
  content: '';
  position: absolute; inset: 0; z-index: -1;
  pointer-events: none; opacity: .24;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='3'/%3E%3C/filter%3E%3Crect width='140' height='140' filter='url(%23n)' opacity='.42'/%3E%3C/svg%3E");
}
.page-head__grid { display: block; width: 100%; position: relative; z-index: 1; }
.page-head__copy { max-width: 46rem; }
.page-head .crumbs { color: rgba(255,255,255,.6); }
.page-head .crumbs a:hover { color: var(--gold); }
.page-head .crumbs [aria-current] { color: rgba(255,255,255,.85); }
.page-head .kicker { color: var(--gold); }
.page-head__title {
  margin-top: var(--s-4);
  font-size: clamp(2.6rem, 6.2vw, 5.6rem);
  line-height: 0.96;
  letter-spacing: -0.035em;
  color: #fff;
}
.page-head__title .cool, .page-head__title .hot, .page-head__title em { color: var(--gold); font-style: normal; }
.page-head__lede { margin-top: var(--s-5); color: rgba(255,255,255,.82); font-size: var(--t-md); }
.page-head__note {
  margin-top: var(--s-4);
  max-width: 62ch;
  font-size: var(--t-xs);
  line-height: 1.6;
  color: rgba(255,255,255,.58);
}
.page-head .src-note { color: rgba(255,255,255,.55); }
.page-head .src-note__icon { color: var(--gold); }

/* dining.html carries a live "serving right now" panel in its head. It was
   laid out as the right-hand column of the old split; on a photograph it has
   to become a glass panel sitting under the copy instead, or it lands as a
   white card in the middle of the picture. */
.page-head .split-head { display: block; }
.page-head .split-head__side { margin-top: var(--s-5); }
.page-head .store-panel {
  max-width: 30rem;
  padding: var(--s-4) var(--s-5);
  border: 1px solid rgba(255,255,255,.22);
  border-radius: var(--r-md);
  background: rgba(12,11,9,.42);
  backdrop-filter: blur(12px); -webkit-backdrop-filter: blur(12px);
  color: rgba(255,255,255,.82);
}
.page-head .store-panel__head { color: #fff; }
.page-head .store-panel b, .page-head .store-panel strong { color: #fff; }
.page-head__lede a { color: var(--gold); text-decoration: underline; text-underline-offset: 3px; }

/* The photograph is now the background, so its framed copy is switched off
   and only the credit survives, on one line under the lede. */
.page-head__shot {
  position: static;
  display: block;
  margin: var(--s-5) 0 0;
  aspect-ratio: auto;
  background: none;
  box-shadow: none;
  border-radius: 0;
  animation: none;
}
.page-head__shot img { display: none; }
.page-head__shot figcaption {
  position: static;
  display: flex; flex-wrap: wrap; align-items: baseline; gap: .5rem;
  padding: 0;
  background: none;
  font-size: var(--t-xs);
  color: rgba(255,255,255,.55);
}
.page-head__shot figcaption b { font-family: var(--sans); font-size: var(--t-xs); font-weight: 600; color: rgba(255,255,255,.75); }
/* Run as one credit line rather than three touching fragments. */
.page-head__shot figcaption > span::before,
.page-head__shot figcaption > a::before { content: '·'; margin-right: .5rem; opacity: .5; }
.page-head__shot figcaption a { margin: 0; color: rgba(255,255,255,.6); }
.page-head__shot figcaption a:hover { color: var(--gold); }

/* ============================================================== STRIP ====
   The tenant marquee is back. Both reference sites carry one — Brentwood
   scrolls its tenants' logos in greyscale under the fold. Ours scrolls the
   bespoke emblems, because the real logos are not ours to use.
   ======================================================================== */
.strip { display: block; }
.strip__item { background: var(--surface); border-color: var(--line); }
.strip__item .tile { width: 34px; border-radius: var(--r-sm); }
.strip__all { color: var(--gold-deep); }
.strip__all:hover { color: var(--ink); }

/* ============================================================= LOCATION == */
/* This was a hand-drawn "schematic, not to scale" of two roads and a pulsing
   dot, captioned with an apology for not being a map. It is a map's job to be
   a map: OpenStreetMap, at the mall's real coordinates, from the same way the
   footprint on the floor guide cites. */
.locmap {
  border: 1px solid var(--line-2);
  border-radius: var(--r-lg);
  overflow: hidden;
  background: var(--paper-2);
  line-height: 0;
}
.locmap iframe {
  width: 100%;
  height: clamp(300px, 42vw, 460px);
  border: 0;
  display: block;
  filter: saturate(.82) contrast(1.02);
}

/* A shop's head is a nameplate, not a cover: mark, trade, name, whether it is
   open. Without this it inherits the 62vh hero height built for pages that
   have a photograph behind them, and opens on half a screen of black. */
.page-head--compact {
  min-height: 0;
  padding-top: calc(var(--header-h) + clamp(1.75rem, 4vh, 3rem));
  padding-bottom: clamp(1.75rem, 4vw, 2.75rem);
}

/* Chips in a dark head. The base chip is drawn for cream — a grey hairline and
   dimmed ink — so on the near-black band the shop's own status line, the one
   thing you came to the page to read, was the least legible thing on it. */
.page-head .chip--static {
  border-color: rgba(255,255,255,.24);
  background: rgba(255,255,255,.06);
  color: rgba(255,255,255,.88);
}
.page-head .chip--static:hover { border-color: rgba(255,255,255,.24); color: rgba(255,255,255,.88); }
.page-head .status { color: rgba(255,255,255,.88); }
.page-head .status[data-state="open"] { color: #8FD8B0; }
.page-head .status[data-state="soon"],
.page-head .status[data-state="closing"] { color: var(--gold); }
.page-head .status__detail { color: rgba(255,255,255,.66); }
