/* ============================================================
   UPSIDE PROPERTY — Design tokens & base
   Prototype rebuild · design language adapted from client reference
   ============================================================ */

:root {
  /* ---- Brand palette ----
     Taken directly from the client's own brand:
       --accent   #ed1c24  the red in the Upside logo (house mark,
                           "OP"/"DE", PROPERTY LLC / REALTY)
       --accent-2 #b70200  the darker red their site uses on hover
       --brand-grey #666666 the grey of the UPSIDE wordmark
     Their live site uses #ed1c24 on 68 declarations, so this is the
     real brand colour, not an approximation. */
  --ink: #0a0a0a;
  --ink-2: #111111;
  --ink-3: #1a1a1a;
  --paper: #f7f7f7;
  --paper-2: #ffffff;
  --mist: #ececec;
  --mist-2: #e0e0e0;

  /* --accent        the exact brand red, used for text, icons and borders */
  --accent: #ed1c24;
  /* --accent-btn    white text sits on this. The exact brand red gives white
     text a 4.38:1 contrast, just under the WCAG AA minimum of 4.5:1. This
     shade is 2% darker — visually indistinguishable, passes at 4.55:1. */
  --accent-btn: #e81b23;
  --accent-2: #b70200;
  --accent-deep: #c41219;
  --accent-soft: rgba(237, 28, 36, 0.10);

  /* the grey in the UPSIDE wordmark */
  --brand-grey: #666666;

  /* ---- Form feedback ----
     The brand colour is red (#ed1c24), so red cannot also mean "you made a
     mistake" — on this site it reads as the house colour rather than a
     warning. Form states therefore use their own semantic colours:
       ok   a reassuring light green for "this is correct / sent"
       warn a single muted amber-red for genuine problems only
     Keeping these separate from --accent means brand red can change without
     silently repainting every form state. */
  --ok: #2f7d43;            /* text + borders on white — 5.1:1, passes AA */
  --ok-soft: rgba(47, 125, 67, 0.09);
  --ok-line: rgba(47, 125, 67, 0.34);
  --ok-tint: #eef7f0;       /* the very light green fill */
  --warn: #a8541f;          /* only for real failures, never for validation */
  --warn-soft: rgba(168, 84, 31, 0.08);
  --warn-line: rgba(168, 84, 31, 0.32);
  /* "we filled this in for you" — informative: not good, not bad */
  --info: #2b5c86;
  --info-soft: rgba(43, 92, 134, 0.08);
  --info-line: rgba(43, 92, 134, 0.30);
  --info-tint: #f2f7fb;

  /* deep near-black red for dark sections that need warmth */
  --navy: #1c1c1c;
  --navy-2: #262626;

  /* ---- Text ---- */
  --tx: #101010;
  --tx-2: #666666;
  /* small muted text. One value cannot serve both backgrounds:
     #767676 is the darkest grey-light that clears AA on white (4.54:1),
     #a8a8a8 clears AA on the near-black sections (8.33:1). */
  --tx-3: #767676;
  --tx-3-ink: #a8a8a8;
  --tx-inv: #ffffff;
  --tx-inv-2: rgba(255, 255, 255, 0.66);
  --tx-inv-3: rgba(255, 255, 255, 0.42);

  /* ---- Lines & glass ---- */
  --line: rgba(10, 10, 10, 0.10);
  --line-2: rgba(10, 10, 10, 0.18);
  --line-inv: rgba(255, 255, 255, 0.14);
  --line-inv-2: rgba(255, 255, 255, 0.26);
  --glass: rgba(250, 249, 247, 0.62);
  --glass-dark: rgba(16, 16, 16, 0.34);
  --glass-chip: rgba(255, 255, 255, 0.30);

  /* ---- Radii ---- */
  --r-xs: 6px;
  --r-sm: 12px;
  --r-md: 18px;
  --r-lg: 26px;
  --r-xl: 34px;
  --r-pill: 999px;

  /* ---- Shadow ---- */
  --sh-sm: 0 2px 10px rgba(10, 10, 10, 0.06);
  --sh-md: 0 14px 40px rgba(10, 10, 10, 0.10);
  --sh-lg: 0 34px 80px rgba(10, 10, 10, 0.16);

  /* ---- Type ---- */
  --f-display: "Archivo", "Helvetica Neue", Arial, sans-serif;
  --f-body: "Inter", "Helvetica Neue", Arial, sans-serif;
  --f-serif: "Instrument Serif", "Times New Roman", serif;

  /* ---- Frame ---- */
  --frame-w: 1440px;
  --gut: 48px;
  --nav-h: 68px;
}

/* ============================================================
   Reset
   ============================================================ */
*,
*::before,
*::after { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }

body {
  margin: 0;
  background: var(--mist);
  color: var(--tx);
  font-family: var(--f-body);
  font-size: 16px;
  line-height: 1.6;
  font-weight: 400;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  /* `hidden` on body makes BODY the scroll container instead of the
     viewport. That breaks three things at once, on every page:
       * window.scrollY stays 0, so the sticky-header scroll handler never
         sees the real position
       * position: sticky inside the page stops sticking
       * on a phone the browser address bar collapsing changes the visual
         viewport, and body-as-scroller fights it — the jitter around the
         header
     `clip` hides horizontal overflow WITHOUT creating a scroll container,
     which is what was wanted here. `hidden` stays first as a fallback for
     browsers that do not support clip. */
  overflow-x: hidden;
  overflow-x: clip;
}

body.no-scroll { overflow: hidden; }

img,
svg,
video { display: block; max-width: 100%; }

a { color: inherit; text-decoration: none; }

button,
input,
select,
textarea {
  font: inherit;
  color: inherit;
}

button { background: none; border: 0; cursor: pointer; }

h1, h2, h3, h4, h5, h6, p, figure, blockquote, ul, ol {
  margin: 0;
  padding: 0;
}

ul, ol { list-style: none; }

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

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

/* ============================================================
   Typography scale
   ============================================================ */
.h-display,
.h1, .h2, .h3, .h4 {
  font-family: var(--f-display);
  font-weight: 700;
  line-height: 1.02;
  letter-spacing: -0.035em;
  text-wrap: balance;
}

.h1 { font-size: clamp(2.6rem, 6.4vw, 5.4rem); }
.h2 { font-size: clamp(2.05rem, 4.4vw, 3.7rem); }
.h3 { font-size: clamp(1.5rem, 2.6vw, 2.3rem); letter-spacing: -0.028em; line-height: 1.1; }
.h4 { font-size: clamp(1.15rem, 1.7vw, 1.5rem); letter-spacing: -0.02em; line-height: 1.2; }

/* italic serif accent used inside headlines */
.em {
  font-family: var(--f-serif);
  font-style: italic;
  font-weight: 400;
  letter-spacing: -0.01em;
  padding-right: 0.04em;
}

.lead {
  font-size: clamp(1rem, 1.15vw, 1.1rem);
  color: var(--tx-2);
  line-height: 1.68;
  max-width: 46ch;
}

.body-sm { font-size: 0.9rem; line-height: 1.62; color: var(--tx-2); }
.body-xs { font-size: 0.8rem; line-height: 1.55; color: var(--tx-3); }

/* fine uppercase micro-label with a bullet, e.g. "• NAVIGATION" */
.micro {
  font-family: var(--f-body);
  font-size: 0.64rem;
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--tx-3);
  display: inline-flex;
  align-items: center;
  gap: 0.5em;
}

.micro::before {
  content: "";
  width: 4px;
  height: 4px;
  border-radius: 50%;
  background: currentColor;
  flex: none;
  opacity: 0.8;
}

/* "// small note" comment style */
.comment {
  font-family: var(--f-body);
  font-size: 0.68rem;
  font-weight: 500;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--tx-3);
}

.comment::before { content: "// "; opacity: 0.55; }

.on-dark .micro, .on-dark .comment,
.dark .micro, .dark .comment { color: var(--tx-inv-3); }

/* Small muted text inside dark sections/ons. --tx-3 is tuned for light
   backgrounds (AA on white), so on dark surfaces it is swapped for the
   lighter ink variant. This is what makes one token safe on both. */
.on-dark, .dark, .footer, .ai__foot {
  --tx-3: var(--tx-3-ink);
}

.on-dark, .dark { color: var(--tx-inv); }
.on-dark .lead, .dark .lead { color: var(--tx-inv-2); }

/* section index, e.g. /01 */
.idx {
  font-family: var(--f-body);
  font-size: 0.74rem;
  font-weight: 500;
  letter-spacing: 0.04em;
  color: var(--tx-3);
}

/* ============================================================
   Layout
   ============================================================ */
.frame {
  width: 100%;
  max-width: var(--frame-w);
  margin: 26px auto;
  background: var(--paper);
  border-radius: var(--r-xl);
  overflow: clip;
  box-shadow: var(--sh-lg);
  position: relative;
}

.shell {
  width: 100%;
  max-width: 1240px;
  margin: 0 auto;
  padding: 0 var(--gut);
}

.section { padding: clamp(56px, 7.5vw, 108px) 0; }
.section-sm { padding: clamp(38px, 4.6vw, 64px) 0; }
.dark { background: var(--ink); color: var(--tx-inv); }
.white { background: var(--paper-2); }

.stack-xs { display: flex; flex-direction: column; gap: 10px; }
.stack-sm { display: flex; flex-direction: column; gap: 18px; }
.stack-md { display: flex; flex-direction: column; gap: 28px; }
.stack-lg { display: flex; flex-direction: column; gap: 48px; }

.row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 32px;
}

.hr { height: 1px; background: var(--line); border: 0; margin: 0; }
.dark .hr, .hr-inv { background: var(--line-inv); }

.sr-only {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}

.skip-link {
  position: absolute;
  left: 50%;
  top: -80px;
  transform: translateX(-50%);
  z-index: 999;
  background: var(--ink);
  color: #fff;
  padding: 12px 22px;
  border-radius: var(--r-pill);
  font-size: 0.85rem;
  transition: top 0.2s ease;
}

.skip-link:focus { top: 12px; }

/* ============================================================
   Responsive gutters
   ============================================================ */
@media (max-width: 900px) {
  :root { --gut: 24px; --frame-w: 100%; }
  .frame { margin: 0; border-radius: 0; box-shadow: none; }
}

@media (max-width: 560px) {
  :root { --gut: 18px; }
  /* Was 15px, i.e. SMALLER than the 16px desktop base. That is backwards: a
     phone is held further away than a laptop, it is the only device most
     visitors use, and text that is already small becomes unreadable in
     sunlight or for anyone over forty. Raised so phones get the largest
     body text on the site rather than the smallest.

     17px rather than 18: most body copy here is rem-based, so this scales
     the whole page at once, and 18 started pushing headings with long
     words ("Manage my property") past the screen edge on a 360px phone. */
  body { font-size: 17px; }
}

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

/* ============================================================
   Long unbreakable strings
   ------------------------------------------------------------
   An email address is one unbreakable token, so at 320px
   johnduncan@upsidepropertysc.com ran 11px past the right edge of
   the contact page — the last remaining overflow anywhere on the
   site. Text does not wrap inside a word by default, and an email
   address is a single word.

   `anywhere` rather than `break-word` because it also lets the
   browser shrink the min-content width, which is what stops the
   parent from being forced wider than the screen.
   ============================================================ */
a[href^="mailto:"], a[href^="tel:"], .body-xs, .body-sm, .micro, p, li {
  overflow-wrap: anywhere;
}
/* Headings keep normal word breaking — `anywhere` on a big heading looks
   broken, and headings rarely contain an email address. */
h1, h2, h3, h4 { overflow-wrap: break-word; }

/* Phones and tablets: the page only scrolls up and down. body already
   clips sideways overflow (overflow-x: clip, above), and a sideways swipe on
   the page itself does nothing (touch-action). Rows that are meant to swipe
   (photo strips, carousels) and maps are their own scroll areas and keep
   working, and pinch-zoom stays on.
   Nothing is set on <html>: overflow on the root element changes how iPhone
   Safari places fixed bars while its toolbar slides back in, which left the
   listing page's Contact / Request a tour bar covered by a grey box. */
@media (max-width: 1024px) {
  body { touch-action: pan-y pinch-zoom; }
}
