/* =====================================================================
   PIXACTLY — shared brand stylesheet, version 1
   https://pixactly.ai/brand/v1/pixactly.css

   One stylesheet for the pixactly.ai website and every Pixactly app, so
   the look is changed in one place. Built 7 Oct 2026 from the hub's
   sign-in and registration pages (main.pixactly.ai), which set the
   look: navy with a faint grid, Space Grotesk and IBM Plex type, rounded
   cards with a thin cyan edge, and the standee swimmer photo that
   rearranges itself for every screen size.

   Owned by the pixactly.ai website. Apps load this file and keep only
   their app-specific styles in their own stylesheets. A change to
   anything in here is made here, not copied into an app.

   House rules for this file
   - Brand-level pieces only: colours, fonts, page background, logo,
     photos and the two photo layouts, cards, buttons, badges and form
     fields. Anything that belongs to one site or one app lives in that
     site's or app's own stylesheet.
   - Every class here starts with "px-", so loading this file never
     restyles an element that hasn't opted in. The only rules without the
     prefix are the colour variables (the same values every app already
     uses) and the page base in section 3 (reset, body font, background
     grid, heading font), which every app already has.
   - v1 only ever gets compatible changes: new classes and bug fixes. A
     change that would alter how an existing class looks on a page that
     already uses it goes into /brand/v2/ instead, so an app's look never
     changes until that app chooses to move.
   - Paths in here (fonts, photos) are relative to this file, so they
     point at pixactly.ai wherever the file is loaded from. Browsers only
     use a font from another (sub)domain when the font response carries
     Access-Control-Allow-Origin; the website's _headers file sets it for
     everything under /brand/.
   ===================================================================== */


/* ── 1. FONTS ───────────────────────────────────────────────────────────
   Self-hosted (no request to Google). Space Grotesk 500/700 for headings,
   the wordmark and buttons; IBM Plex Sans 400/500/600 for text; IBM Plex
   Mono 500/600 for small uppercase labels. Each weight comes as a basic
   Latin file and an extended-Latin file (which carries ₹); a browser only
   downloads a file when the page uses a character in its range. SIL Open
   Font License — see fonts/OFL-*.txt. */
@font-face {
  font-family: 'Space Grotesk';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url(fonts/space-grotesk-latin-500-normal.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Space Grotesk';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url(fonts/space-grotesk-latin-ext-500-normal.woff2) format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'Space Grotesk';
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url(fonts/space-grotesk-latin-700-normal.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Space Grotesk';
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url(fonts/space-grotesk-latin-ext-700-normal.woff2) format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'IBM Plex Sans';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url(fonts/ibm-plex-sans-latin-400-normal.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'IBM Plex Sans';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url(fonts/ibm-plex-sans-latin-ext-400-normal.woff2) format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'IBM Plex Sans';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url(fonts/ibm-plex-sans-latin-500-normal.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'IBM Plex Sans';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url(fonts/ibm-plex-sans-latin-ext-500-normal.woff2) format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'IBM Plex Sans';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url(fonts/ibm-plex-sans-latin-600-normal.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'IBM Plex Sans';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url(fonts/ibm-plex-sans-latin-ext-600-normal.woff2) format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'IBM Plex Mono';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url(fonts/ibm-plex-mono-latin-500-normal.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'IBM Plex Mono';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url(fonts/ibm-plex-mono-latin-ext-500-normal.woff2) format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'IBM Plex Mono';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url(fonts/ibm-plex-mono-latin-600-normal.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'IBM Plex Mono';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url(fonts/ibm-plex-mono-latin-ext-600-normal.woff2) format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}


/* ── 2. COLOURS AND FONT STACKS ───────────────────────────────────────── */
:root {
  --navy:   #0B1F3A;   /* page background */
  --card:   #162D4A;   /* cards */
  --dkgray: #1E3A5F;   /* bars and panels */
  --blue:   #0077B6;   /* borders and hover states */
  --cyan:   #00B4D8;   /* brand accent, primary buttons, "Measure." */
  --green:  #00C896;   /* success */
  --amber:  #FFC000;   /* warnings */
  --red:    #E05252;   /* errors */
  --gray:   #8090A0;   /* secondary text */
  --white:  #FFFFFF;   /* text */

  --px-font-display: 'Space Grotesk', Arial, sans-serif;
  --px-font-body:    'IBM Plex Sans', Arial, sans-serif;
  --px-font-mono:    'IBM Plex Mono', 'Courier New', monospace;
}


/* ── 3. PAGE BASE ─────────────────────────────────────────────────────── */
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }

html, body {
  background-color: var(--navy);
  color: var(--white);
  font-family: var(--px-font-body);
  font-size: 16px;
  -webkit-font-smoothing: antialiased;
}
/* The faint 44px grid: lines of 4.5% white. A texture, not a pattern
   meant to be noticed. */
body {
  min-height: 100vh;
  background-image:
    linear-gradient(rgba(255, 255, 255, 0.045) 1px, transparent 1px),
    linear-gradient(90deg, rgba(255, 255, 255, 0.045) 1px, transparent 1px);
  background-size: 44px 44px;
}
h1, h2, h3 { font-family: var(--px-font-display); }


/* ── 4. LOGO AND WORDMARK ─────────────────────────────────────────────── */
.px-brand {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  font-family: var(--px-font-display);
  font-size: 20px;
  font-weight: 700;
  letter-spacing: 1px;
  color: var(--cyan);
  text-decoration: none;
  white-space: nowrap;
}
.px-brand img { display: block; height: 40px; width: auto; }


/* ── 5. TYPE ──────────────────────────────────────────────────────────── */
/* Small uppercase, letter-spaced label: section eyebrows, step captions. */
.px-eyebrow {
  font-family: var(--px-font-mono);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.72);
}
.px-muted { color: var(--gray); }

/* The headline that sits on a photo ("Swim. <em>Measure.</em> Improve.").
   Owner's rule: it stays on ONE line at every width — nowrap plus a size
   that scales with the screen. Re-check against the real Space Grotesk if
   the words ever change. <em> is the cyan word. */
.px-headline {
  font-family: var(--px-font-display);
  font-weight: 700;
  font-size: clamp(20px, 6.1vw, 30px);
  line-height: 1.05;
  letter-spacing: -0.01em;
  white-space: nowrap;
  text-shadow: 0 2px 18px rgba(0, 0, 0, 0.5);
}
.px-headline em { font-style: normal; color: var(--cyan); }
.px-tagline {
  font-size: 13px;
  line-height: 1.45;
  color: rgba(255, 255, 255, 0.82);
  margin-top: 6px;
  text-shadow: 0 1px 10px rgba(0, 0, 0, 0.5);
}
@media (min-width: 900px) {
  .px-headline { font-size: clamp(28px, 3.3vw, 46px); }
  .px-tagline { font-size: 16px; max-width: 460px; margin-top: 10px; }
}


/* ── 6. BUTTONS ───────────────────────────────────────────────────────── */
/* Works on <a> and <button>. Primary is cyan filled, outline is the real
   alternative next to it. Both carry a 1.5px border so the two are exactly
   the same height side by side or stacked. */
.px-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 13px 22px;
  border: 1.5px solid transparent;
  border-radius: 10px;
  font-family: var(--px-font-display);
  font-size: 15px;
  font-weight: 700;
  line-height: 1.2;
  text-align: center;
  text-decoration: none;
  white-space: nowrap;
  cursor: pointer;
  transition: background-color 0.15s ease, color 0.15s ease,
              border-color 0.15s ease, box-shadow 0.15s ease;
}
.px-btn:focus-visible { outline: 2px solid var(--cyan); outline-offset: 3px; }
.px-btn-primary {
  background: var(--cyan);
  border-color: var(--cyan);
  color: var(--navy);
  box-shadow: 0 8px 20px rgba(0, 180, 216, 0.3);
}
.px-btn-primary:hover { background: var(--blue); border-color: var(--blue); color: var(--white); }
.px-btn-outline { background: transparent; border-color: var(--cyan); color: var(--cyan); }
.px-btn-outline:hover { background: rgba(0, 180, 216, 0.1); }
.px-btn-sm { padding: 8px 14px; font-size: 13.5px; border-radius: 8px; }
.px-btn-primary.px-btn-sm { box-shadow: none; }
.px-btn-full { width: 100%; white-space: normal; }
.px-btn:disabled,
.px-btn[aria-disabled="true"] { opacity: 0.55; cursor: not-allowed; box-shadow: none; }

/* "— Don't have an account? —" line between two alternative buttons. */
.px-divider {
  display: flex;
  align-items: center;
  gap: 12px;
  margin: 16px 0;
  font-size: 13px;
  color: var(--gray);
}
.px-divider::before,
.px-divider::after { content: ''; flex: 1; height: 1px; background: rgba(255, 255, 255, 0.14); }


/* ── 7. CARDS AND BADGES ──────────────────────────────────────────────── */
.px-card {
  background: var(--card);
  border: 1px solid rgba(0, 180, 216, 0.35);
  border-radius: 18px;
  box-shadow: 0 20px 50px rgba(0, 0, 0, 0.45);
  padding: 24px 22px;
}
.px-badge {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-family: var(--px-font-mono);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--cyan);
  background: rgba(0, 180, 216, 0.1);
  border: 1px solid rgba(0, 180, 216, 0.4);
  border-radius: 999px;
  padding: 4px 10px;
  white-space: nowrap;
}


/* ── 8. FORM FIELDS ───────────────────────────────────────────────────── */
.px-field { margin-bottom: 16px; }
.px-label {
  display: block;
  font-family: var(--px-font-mono);
  font-size: 11px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--gray);
  margin-bottom: 6px;
}
/* Set back on the page's navy (not dkgray) so the field sits inside its
   card instead of competing with it. */
.px-input {
  display: block;
  width: 100%;
  padding: 12px 14px;
  background: rgba(11, 31, 58, 0.8);
  border: 1px solid rgba(255, 255, 255, 0.12);
  border-radius: 10px;
  color: var(--white);
  font-family: var(--px-font-body);
  font-size: 15px;
}
.px-input::placeholder { color: rgba(255, 255, 255, 0.38); }
.px-input:focus { outline: none; border-color: var(--cyan); box-shadow: 0 0 0 3px rgba(0, 180, 216, 0.25); }
textarea.px-input { min-height: 120px; resize: vertical; line-height: 1.5; }
/* Chrome/Edge paint autofilled fields white unless overridden this way. */
.px-input:-webkit-autofill,
.px-input:-webkit-autofill:hover,
.px-input:-webkit-autofill:focus {
  -webkit-text-fill-color: var(--white);
  -webkit-box-shadow: 0 0 0 1000px #0E2444 inset;
  box-shadow: 0 0 0 1000px #0E2444 inset;
  caret-color: var(--white);
  transition: background-color 9999s ease-in-out 0s;
}


/* ── 9. PHOTOS ────────────────────────────────────────────────────────────
   A photo is picked with one class. The layouts below take its framing
   from these variables, so each photo can be framed on its subject:
     --px-photo-pos       phones and tablets (the banner)
     --px-photo-pos-wide  from 900px (the tall left-hand column)
     --px-photo-pos-card  a short, wide panel, e.g. a card header
   A site or app adds its own photos the same way, in its own stylesheet. */
.px-photo-swim {
  /* The poolside standee photo, 1600 x 850. Banner: cropped from the top
     so the swimmer's face stays in view. Column: re-centred on him. */
  background-image: url(images/hero-swimmer-standee.jpg);
  --px-photo-pos: 55% 0%;
  --px-photo-pos-wide: center 35%;
  --px-photo-pos-card: center 42%;
}


/* ── 10. SPLIT PHOTO LAYOUT ───────────────────────────────────────────────
   The hub's sign-in layout.
   Under 900px: the photo is a banner across the top, at least 430px tall,
   fading into navy at the bottom. The caption (headline) sits in the water
   just below the swimmer's chin. The content card starts 28px higher,
   over the fade, so photo and card read as one piece.
   From 900px: two columns (1.15fr / 1fr). The photo fills the left column
   at full screen height and stays put while the right side scrolls; two
   gradients melt its right edge and bottom into navy. The card sits
   vertically centred on the right, at most 460px wide.

     <div class="px-split">
       <div class="px-split-photo px-photo-swim" role="img" aria-label="…">
         <div class="px-split-caption">
           <p class="px-headline">Swim. <em>Measure.</em> Improve.</p>
           <p class="px-tagline">…</p>
         </div>
       </div>
       <div class="px-split-main"><div class="px-card">…</div></div>
     </div>                                                                */
.px-split { position: relative; }
.px-split-photo {
  position: relative;
  min-height: 430px;
  background-repeat: no-repeat;
  background-size: cover;
  background-position: var(--px-photo-pos, center top);
}
.px-split-photo::after {
  content: '';
  position: absolute;
  inset: 0;
  background: linear-gradient(180deg,
    rgba(11, 31, 58, 0.10) 0%,
    rgba(11, 31, 58, 0.15) 55%,
    rgba(11, 31, 58, 0.90) 80%,
    var(--navy) 100%);
}
.px-split-caption {
  position: relative;
  z-index: 1;
  min-height: 430px;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  padding: 18px 20px 52px;
}
.px-split-main {
  position: relative;
  z-index: 2;
  margin-top: -28px;
  padding: 0 16px 40px;
}
.px-split-main > .px-card { max-width: 440px; margin: 0 auto; }

@media (min-width: 900px) {
  .px-split {
    display: grid;
    grid-template-columns: 1.15fr 1fr;
    min-height: 100vh;
  }
  .px-split-photo {
    position: sticky;
    top: 0;
    height: 100vh;
    min-height: 0;
    background-position: var(--px-photo-pos-wide, center 35%);
  }
  .px-split-photo::after {
    background:
      linear-gradient(90deg, rgba(11, 31, 58, 0.05) 40%, var(--navy) 100%),
      linear-gradient(0deg, rgba(11, 31, 58, 0.85) 0%, transparent 45%);
  }
  .px-split-caption { min-height: 100vh; padding: 36px 48px; }
  .px-split-main {
    display: flex;
    align-items: center;
    justify-content: center;
    margin-top: 0;
    padding: 40px;
  }
  .px-split-main > .px-card { width: 100%; max-width: 460px; margin: 0; padding: 34px 32px; }
}


/* ── 11. WATER STRIP ──────────────────────────────────────────────────────
   The hub's registration-step header. Instead of the whole photo, an inner
   page shows only its bottom (water and arms, no face) as a band across
   the top, so every page reads as a continuation of the photo pages.
   Under 744px the photo is drawn 395px tall; from 744px it is drawn at the
   full page width. Either way its bottom 150px shows, darkened, fading to
   navy at 150px; the band then fades into the page's grid over another
   50px, so there is no hard edge.

     <div class="px-strip-page">
       <div class="px-strip px-photo-swim" aria-hidden="true"></div>
       … page content …
     </div>                                                                */
.px-strip-page { position: relative; isolation: isolate; }
.px-strip {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 200px;
  z-index: -1;
  pointer-events: none;
  background-repeat: no-repeat;
  background-size: auto 395px;
  background-position: center bottom 50px;
}
.px-strip::after {
  content: '';
  position: absolute;
  inset: 0;
  background: linear-gradient(180deg,
    rgba(11, 31, 58, 0.62) 0px,
    rgba(11, 31, 58, 0.62) 90px,
    var(--navy) 150px,
    rgba(11, 31, 58, 0) 200px);
}
@media (min-width: 744px) {
  .px-strip { background-size: 100% auto; }
}
