/* ============================================================================
   The Travel Stations — design tokens and the shared component vocabulary.

   Loaded before every other stylesheet. Everything visual on the site resolves
   to a variable declared here, so a rebrand is an edit to this file rather than
   a sweep through thirty others — retinting the ramps retints the whole site.

   Second pass: the client asked to match a reference layout ("YourTravel")
   pixel-for-pixel, not just structurally — and that reference is blue-led,
   not teal-led: a royal blue carries navigation, links and every primary
   button, a light sky blue is the one decorative highlight on the hero
   headline, and green is demoted to a small secondary accent (a checkmark
   icon, one offer card) rather than the brand's main action colour. So the
   ramp that used to be a deep teal is royal blue here, and the ramp that used
   to be a bright kelly green (the site's main call-to-action colour) now only
   fills that narrow secondary role. Ink goes navy-black rather than teal-black
   on dark surfaces for the same reason — the footer and every dark band need
   to read as the same blue identity, not a leftover green-black. The logo's
   red still stays confined to the logo file itself; nothing here reaches for
   it as a UI colour.
   ========================================================================== */

:root {
    /* -- Ink: dark surfaces, headings, the footer ------------------------- */
    --pt-ink-900: #0A1830;
    --pt-ink-800: #11244A;
    --pt-ink-700: #16305E;
    --pt-ink-600: #1E3F73;
    --pt-ink-500: #35578C;

    /* -- Brand blue: primary actions, links, focus -------------------------- */
    --pt-blue-800: #102A5C;
    --pt-blue-700: #15398A;
    --pt-blue-600: #1E56C7;
    --pt-blue-500: #2E74E5;
    --pt-blue-300: #6FB2F5;
    --pt-blue-200: #BFDCFB;
    --pt-blue-100: #E1EEFD;
    --pt-blue-050: #F3F8FE;

    /* -- Accent green: a small secondary highlight only — a checkmark icon,
       one offer card — never the site's main call-to-action colour now that
       blue carries that role. ---------------------------------------------- */
    --pt-lime-700: #1E8449;
    --pt-lime-600: #22A55D;
    --pt-lime-500: #2FBE6C;
    --pt-lime-300: #8FE0B0;
    --pt-lime-100: #E1F8EA;

    /* -- Two more one-off hues, used only by the "why choose us" icon row to
       match the reference's five-colour icon treatment (blue/green/purple/
       orange/pink) — not full ramps, since nothing else on the site needs
       them. ------------------------------------------------------------- */
    --pt-purple: #7C4FE0;
    --pt-purple-soft: #EEE6FC;
    --pt-pink: #E23B84;
    --pt-pink-soft: #FCE4EE;

    /* -- Neutrals -------------------------------------------------------- */
    --pt-paper: #FFFFFF;
    --pt-sand: #F8F7F2;
    --pt-sand-deep: #EFEEE5;
    --pt-slate-800: #23324A;
    --pt-slate-700: #3C4A5E;
    --pt-slate-600: #566378;
    --pt-slate-500: #74819A;
    --pt-slate-400: #9AA5B8;
    --pt-line: #E4E8EE;
    --pt-line-soft: #EEF1F5;

    /* -- Status. Warning deliberately doubles as the site's orange accent —
       the reference site's script highlights and phone number are already
       exactly this hue, so there's no separate token to invent. ---------- */
    --pt-success: #17795E;
    --pt-success-soft: #E4F4EF;
    --pt-warning: #F39C2C;
    --pt-warning-soft: #FDF0DC;
    --pt-danger: #B23B36;
    --pt-danger-soft: #FBECEB;

    /* -- Semantic aliases. Views should reach for these, not the ramps. --- */
    --pt-bg: var(--pt-sand);
    --pt-surface: var(--pt-paper);
    --pt-text: var(--pt-slate-800);
    --pt-text-muted: var(--pt-slate-600);
    --pt-text-faint: var(--pt-slate-500);
    --pt-heading: var(--pt-ink-800);
    --pt-primary: var(--pt-blue-600);
    --pt-primary-hover: var(--pt-blue-700);
    --pt-accent: var(--pt-lime-500);
    --pt-border: var(--pt-line);

    /* -- Type ------------------------------------------------------------
       Outfit for headings and UI (geometric, confident, reads premium at
       weight); Plus Jakarta Sans for body copy (taller x-height, easier at
       15px); Instrument Serif italic as the signature accent on eyebrows and
       pull quotes. That third face is the thing that stops the site reading as
       a bootstrap template — it appears only a handful of times per page. */
    --pt-font-display: "Outfit", "Segoe UI", system-ui, -apple-system, sans-serif;
    --pt-font-body: "Plus Jakarta Sans", "Segoe UI", system-ui, -apple-system, sans-serif;
    --pt-font-accent: "Instrument Serif", Georgia, "Times New Roman", serif;

    /* Fluid scale — clamp() so the page reflows smoothly instead of
       stair-stepping at each breakpoint. */
    --pt-text-xs: 0.75rem;
    --pt-text-sm: 0.8125rem;
    --pt-text-base: 0.9375rem;
    --pt-text-md: 1rem;
    --pt-text-lg: 1.125rem;
    --pt-text-xl: clamp(1.25rem, 0.5vw + 1.1rem, 1.5rem);
    --pt-h3: clamp(1.35rem, 0.8vw + 1.15rem, 1.75rem);
    --pt-h2: clamp(1.75rem, 1.6vw + 1.35rem, 2.75rem);
    --pt-h1: clamp(2.25rem, 3.4vw + 1.4rem, 4.25rem);

    /* -- Space, radius, elevation ---------------------------------------- */
    --pt-gap-xs: 0.375rem;
    --pt-gap-sm: 0.625rem;
    --pt-gap: 1rem;
    --pt-gap-lg: 1.5rem;
    --pt-gap-xl: 2.25rem;
    --pt-section-y: clamp(3.25rem, 6vw, 6rem);

    --pt-radius-sm: 8px;
    --pt-radius: 14px;
    --pt-radius-lg: 20px;
    --pt-radius-xl: 28px;
    --pt-radius-pill: 999px;

    /* Layered rather than single-blur: a tight contact shadow plus a wide
       ambient one is what makes a card sit on the page instead of floating
       above a grey smudge. */
    --pt-shadow-sm: 0 1px 2px rgba(17, 36, 74, .06), 0 1px 3px rgba(17, 36, 74, .04);
    --pt-shadow: 0 2px 4px rgba(17, 36, 74, .05), 0 8px 20px rgba(17, 36, 74, .07);
    --pt-shadow-lg: 0 4px 8px rgba(17, 36, 74, .06), 0 18px 44px rgba(17, 36, 74, .12);
    --pt-shadow-xl: 0 8px 16px rgba(17, 36, 74, .08), 0 32px 72px rgba(17, 36, 74, .18);
    --pt-ring: 0 0 0 3px rgba(30, 86, 199, .28);

    --pt-ease: cubic-bezier(.2, .7, .3, 1);
    --pt-ease-out: cubic-bezier(.16, 1, .3, 1);


    /* -- Legacy brand aliases --------------------------------------------
       The product stylesheets written before this design system (tours,
       cruise, visas, sightseeing, destinations, services, account, the
       content and legal pages) resolve their colours from these names, which
       used to be declared in header.css. Mapping them onto the new ramps
       re-themes all sixteen of those sheets from one place instead of
       rewriting each by hand — and keeps them in step with any future
       palette change rather than drifting again.

       "gold" was the legacy name for these sheets' primary action colour —
       inherited from an even earlier identity — so it maps to the brand blue
       with no renaming needed; "gold-bright" was their decorative highlight
       slot and maps to the secondary green accent. */
    --brand-navy: var(--pt-ink-800);
    --brand-navy-dark: var(--pt-ink-900);
    --brand-navy-light: var(--pt-ink-600);
    --brand-navy-soft: var(--pt-blue-100);
    --brand-gold: var(--pt-blue-600);
    --brand-gold-bright: var(--pt-lime-500);
    --brand-gold-soft: var(--pt-lime-100);

    /* How far the product search card rides up over the hero above it. The four
       *-search-wrapper rules read this via var(--hero-card-overlap, 220px); that
       220px fallback was measured against the old light hero and, applied to the
       new photographic one, lifted the card clear over the hero's trust strip and
       hid it. Defining the token here sets all four from one place. */
    --hero-card-overlap: 3.5rem;

    --pt-container: 1240px;
    --pt-header-h: 76px;
}

/* ---------------------------------------------------------------- reset -- */

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

html {
    font-size: 15px;
    -webkit-text-size-adjust: 100%;
    scroll-behavior: smooth;
    /* Several sections break out of .container with the
       left:50%;width:100vw;margin-left:-50vw trick. On Windows the scrollbar
       takes layout space, so 100vw measures wider than the visible page and
       those sections force a horizontal scrollbar. Clipping is the standard
       fix — it only ever hides background bleed past the visible edge. */
    overflow-x: hidden;
}

@media (min-width: 768px) { html { font-size: 16px; } }

body {
    margin: 0;
    overflow-x: hidden;
    background: var(--pt-bg);
    color: var(--pt-text);
    font-family: var(--pt-font-body);
    font-size: var(--pt-text-base);
    line-height: 1.65;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
}

h1, h2, h3, h4, h5 {
    font-family: var(--pt-font-display);
    color: var(--pt-heading);
    font-weight: 700;
    letter-spacing: -0.022em;
    line-height: 1.15;
    margin: 0 0 var(--pt-gap-sm);
}

h1 { font-size: var(--pt-h1); letter-spacing: -0.035em; }
h2 { font-size: var(--pt-h2); letter-spacing: -0.028em; }
h3 { font-size: var(--pt-h3); }

p { margin: 0 0 var(--pt-gap); }

a { color: var(--pt-primary); text-decoration: none; transition: color .18s var(--pt-ease); }
a:hover { color: var(--pt-primary-hover); }

img { max-width: 100%; height: auto; display: block; }

/* The _Icon partial emits <svg class="icon" viewBox="0 0 24 24"> with no width
   or height of its own. An SVG with no intrinsic size falls back to 300x150, so
   without this every icon that a component does not explicitly size renders as
   a full-screen graphic. Components override it freely; this is only the floor. */
svg.icon {
    width: 16px;
    height: 16px;
    flex: none;
    vertical-align: middle;
}

:focus-visible {
    outline: none;
    box-shadow: var(--pt-ring);
    border-radius: var(--pt-radius-sm);
}

/* Headings take the ink colour by default (rule above). These containers have
   already declared a light text colour for themselves, and the legacy sheets
   relied on the heading simply inheriting it — which the global rule silently
   broke, painting dark-on-dark headings that were invisible against their own
   background (the "Your Passport, Stamped" band was the visible symptom).
   `inherit` hands the decision back to the container.

   :where() keeps the specificity at the ancestor alone, so any component that
   wants a specific heading colour still wins. */
.pt-hero :where(h1, h2, h3, h4, h5),
.pt-cta :where(h1, h2, h3, h4, h5),
.pt-stats :where(h1, h2, h3, h4, h5),
.pt-section--ink :where(h1, h2, h3, h4, h5),
.hotel-enquiry__head :where(h1, h2, h3, h4, h5),
.acc-brand :where(h1, h2, h3, h4, h5),
.cp-hero :where(h1, h2, h3, h4, h5),
.cp-cta :where(h1, h2, h3, h4, h5),
.cd-hero :where(h1, h2, h3, h4, h5),
.td-hero :where(h1, h2, h3, h4, h5),
.sd-hero :where(h1, h2, h3, h4, h5),
.vd-hero :where(h1, h2, h3, h4, h5),
.svc-hero :where(h1, h2, h3, h4, h5),
.lst-hero :where(h1, h2, h3, h4, h5),
.legal-hero :where(h1, h2, h3, h4, h5),
.vp-heading :where(h1, h2, h3, h4, h5),
.tour-consultation-card :where(h1, h2, h3, h4, h5),
.visa-consultation-card :where(h1, h2, h3, h4, h5),
.dest-guide-body :where(h1, h2, h3, h4, h5),
.svc-card-body :where(h1, h2, h3, h4, h5),
.route-card-body :where(h1, h2, h3, h4, h5) {
    color: inherit;
}

/* The site is read almost entirely on phones. Nothing decorative is allowed to
   move for a visitor who has asked the OS to stop it. */
@media (prefers-reduced-motion: reduce) {
    html { scroll-behavior: auto; }
    *, *::before, *::after {
        animation-duration: .001ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: .001ms !important;
    }
}

/* ------------------------------------------------------------- layout --- */

.pt-container,
.container {
    width: 100%;
    max-width: var(--pt-container);
    margin-inline: auto;
    padding-inline: clamp(1rem, 4vw, 2rem);
}

/* Re-establishes a reading column inside a section that has escaped the
   container with the full-bleed trick. */
.wrap {
    max-width: var(--pt-container);
    margin: 0 auto;
    padding: 0 clamp(1rem, 4vw, 2rem);
}

.pt-section { padding-block: var(--pt-section-y); }
.pt-section--tight { padding-block: clamp(2.25rem, 4vw, 3.5rem); }

/* Every stacked landing-page block — .pt-section, .why-us-section,
   .routes-section, .visa-process-section, .visa-consultation-section, the
   testimonials band — pads itself top and bottom with --pt-section-y so it
   still has full breathing room when it is the only thing on the page. Two of
   them back to back therefore doubled up: bottom padding of one plus top
   padding of the next, a band nearly 200px tall of pure empty space between,
   say, "Popular tour packages" and "Trending destinations".
   Every one of these blocks is a literal <section> element, so this collapses
   the seam back to a single unit wherever two sit adjacent, without touching
   the padding value itself — which is what still gives a lone section (one
   preceded by a <div> wrapper like the marquee or search card) its full,
   correct spacing. The hero is excluded: its own bottom spacing is tuned
   separately to seat the search card's negative-margin overlap, and pulling
   the next section up into that would fight it.

   .cp-section/.cp-cta (About/Contact/Blogs/Legal content pages) are also
   excluded, as are .td-section/.sd-section/.cd-section/.vd-section (the Tour/
   Destination/Sightseeing/Cruise/Visa detail pages' own content sections —
   Overview, Itinerary, Route Map, Inclusions, Exclusions, etc.): all of these
   space themselves with a fixed padding (1.5rem 0 3rem, or margin-top: 2.5rem)
   rather than this padding-block convention, so this rule's up-to-6rem pull had
   nothing matching to absorb it and dragged one section up into the content of
   the one before it — most visibly where the pulled section's own box was
   shorter than the pull (a "hidden" map section revealed by JS, or an
   Inclusions panel truncated by "Read more"), which read as one section's
   heading stamped directly over the previous section's text. */
section:not(.pt-hero):not(.cp-section):not(.cp-cta):not(.td-section):not(.sd-section):not(.cd-section):not(.vd-section)
  + section:not(.pt-hero):not(.cp-section):not(.cp-cta):not(.td-section):not(.sd-section):not(.cd-section):not(.vd-section) {
    margin-top: calc(-1 * var(--pt-section-y));
}

/* Full-bleed band that still centres its contents. */
.pt-bleed {
    position: relative;
    left: 50%;
    width: 100vw;
    margin-left: -50vw;
}

.pt-section--sand { background: var(--pt-sand); }
.pt-section--paper { background: var(--pt-paper); }

.pt-section--ink {
    background: var(--pt-ink-800);
    color: rgba(255, 255, 255, .82);
}

.pt-section--ink h2,
.pt-section--ink h3 { color: #fff; }

/* ------------------------------------------------- section headings ----- */

.pt-heading { max-width: 46rem; margin-bottom: var(--pt-gap-xl); }
.pt-heading--center { margin-inline: auto; text-align: center; }

/* The serif italic eyebrow is the site's signature. Used once per section and
   never inside a card, so it stays an accent rather than a texture. */
.pt-eyebrow {
    display: inline-flex;
    align-items: center;
    gap: .5rem;
    font-family: var(--pt-font-accent);
    font-style: italic;
    font-size: 1.0625rem;
    letter-spacing: .01em;
    color: var(--pt-blue-600);
    margin-bottom: .5rem;
}

.pt-eyebrow::before {
    content: "";
    width: 26px;
    height: 2px;
    border-radius: 2px;
    background: linear-gradient(90deg, var(--pt-lime-500), var(--pt-blue-500));
}

.pt-heading--center .pt-eyebrow::before { display: none; }

.pt-section--ink .pt-eyebrow { color: var(--pt-lime-500); }

.pt-heading p {
    color: var(--pt-text-muted);
    font-size: var(--pt-text-lg);
    margin: 0;
}

.pt-section--ink .pt-heading p { color: rgba(255, 255, 255, .68); }

/* ------------------------------------------------------------ buttons --- */

.pt-btn {
    --_bg: var(--pt-primary);
    --_fg: #fff;
    --_bd: transparent;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: .5rem;
    padding: .8rem 1.5rem;
    border: 1px solid var(--_bd);
    border-radius: var(--pt-radius-pill);
    background: var(--_bg);
    color: var(--_fg);
    font-family: var(--pt-font-display);
    font-size: var(--pt-text-base);
    font-weight: 600;
    letter-spacing: .005em;
    line-height: 1.2;
    cursor: pointer;
    white-space: nowrap;
    transition: transform .2s var(--pt-ease), box-shadow .2s var(--pt-ease), background .2s var(--pt-ease), color .2s var(--pt-ease);
}

.pt-btn:hover {
    color: var(--_fg);
    transform: translateY(-2px);
    box-shadow: var(--pt-shadow-lg);
}

.pt-btn:active { transform: translateY(0); }

.pt-btn svg { width: 18px; height: 18px; flex: none; }

.pt-btn--primary {
    --_bg: linear-gradient(135deg, var(--pt-blue-600), var(--pt-blue-700));
    box-shadow: 0 6px 18px rgba(30, 86, 199, .28);
}

.pt-btn--accent {
    --_bg: linear-gradient(135deg, var(--pt-lime-500), var(--pt-lime-600));
    --_fg: var(--pt-ink-800);
    box-shadow: 0 6px 18px rgba(34, 165, 93, .32);
}

.pt-btn--ghost {
    --_bg: transparent;
    --_fg: var(--pt-heading);
    --_bd: var(--pt-border);
}

.pt-btn--ghost:hover { --_bd: var(--pt-blue-500); --_fg: var(--pt-blue-600); }

.pt-btn--on-ink {
    --_bg: rgba(255, 255, 255, .08);
    --_fg: #fff;
    --_bd: rgba(255, 255, 255, .28);
    backdrop-filter: blur(6px);
}

.pt-btn--on-ink:hover { --_bg: rgba(255, 255, 255, .16); }

.pt-btn--lg { padding: 1rem 2rem; font-size: var(--pt-text-md); }
.pt-btn--sm { padding: .55rem 1.1rem; font-size: var(--pt-text-sm); }
.pt-btn--block { width: 100%; }

/* Text link with the accent rule that grows on hover — used instead of a third
   button weight, so a section never has three competing calls to action. */
.pt-link {
    display: inline-flex;
    align-items: center;
    gap: .4rem;
    font-family: var(--pt-font-display);
    font-weight: 600;
    color: var(--pt-blue-600);
    position: relative;
    padding-bottom: 2px;
}

.pt-link::after {
    content: "";
    position: absolute;
    left: 0;
    bottom: 0;
    height: 2px;
    width: 0;
    border-radius: 2px;
    background: var(--pt-lime-500);
    transition: width .3s var(--pt-ease-out);
}

.pt-link:hover::after { width: 100%; }
.pt-link svg { width: 16px; height: 16px; transition: transform .25s var(--pt-ease); }
.pt-link:hover svg { transform: translateX(3px); }

/* -------------------------------------------------------------- cards --- */

.pt-card {
    position: relative;
    display: flex;
    flex-direction: column;
    background: var(--pt-surface);
    border: 1px solid var(--pt-line-soft);
    border-radius: var(--pt-radius-lg);
    overflow: hidden;
    transition: transform .35s var(--pt-ease-out), box-shadow .35s var(--pt-ease-out), border-color .35s var(--pt-ease);
}

.pt-card:hover {
    transform: translateY(-6px);
    border-color: var(--pt-blue-200);
    box-shadow: var(--pt-shadow-lg);
}

.pt-card__media {
    /* Explicit, because the card partials are built from <a><span>…</span></a>
       so the browser would otherwise leave these inline — which collapses the
       aspect-ratio box to zero height and stacks the body text sideways. */
    display: block;
    position: relative;
    flex: none;
    aspect-ratio: 4 / 3;
    overflow: hidden;
    background: var(--pt-sand-deep);
}

.pt-card__media img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    transition: transform .7s var(--pt-ease-out);
}

.pt-card:hover .pt-card__media img { transform: scale(1.07); }

/* Bottom scrim so a badge or price sitting on the image stays legible over a
   bright photo without dimming the whole picture. */
.pt-card__media::after {
    content: "";
    position: absolute;
    inset: auto 0 0;
    height: 55%;
    background: linear-gradient(180deg, transparent, rgba(10, 24, 48, .72));
    pointer-events: none;
}

/* flex column, not just block: when a grid row stretches a card taller than
   its own content (a sibling card in the same row has an extra price/meta
   line this one lacks), this is what lets the card's own bottom row (price,
   actions, whatever the caller renders last) absorb that slack instead of
   leaving it as dead blank space above an oddly-floating button row. */
.pt-card__body { display: flex; flex-direction: column; flex: 1 1 auto; padding: var(--pt-gap-lg); }

.pt-card__title {
    display: block;
    font-family: var(--pt-font-display);
    font-size: var(--pt-text-lg);
    font-weight: 700;
    color: var(--pt-heading);
    margin: 0 0 .35rem;
    line-height: 1.3;
}

.pt-card__meta {
    display: flex;
    align-items: center;
    gap: .4rem;
    color: var(--pt-text-faint);
    font-size: var(--pt-text-sm);
    margin: 0;
}

.pt-card__meta svg { width: 14px; height: 14px; flex: none; }

/* ------------------------------------------------------------- chips ---- */

.pt-chip {
    display: inline-flex;
    align-items: center;
    gap: .35rem;
    padding: .3rem .7rem;
    border-radius: var(--pt-radius-pill);
    background: var(--pt-blue-100);
    color: var(--pt-blue-700);
    font-size: var(--pt-text-xs);
    font-weight: 600;
    line-height: 1.4;
    white-space: nowrap;
}

.pt-chip--accent { background: var(--pt-lime-100); color: var(--pt-lime-700); }
.pt-chip--neutral { background: var(--pt-sand-deep); color: var(--pt-slate-700); }
.pt-chip--success { background: var(--pt-success-soft); color: var(--pt-success); }
.pt-chip--warning { background: var(--pt-warning-soft); color: var(--pt-warning); }
.pt-chip--danger { background: var(--pt-danger-soft); color: var(--pt-danger); }

/* Floating badge on a card image. */
.pt-badge-float {
    position: absolute;
    top: .875rem;
    left: .875rem;
    z-index: 2;
    padding: .35rem .75rem;
    border-radius: var(--pt-radius-pill);
    background: rgba(255, 255, 255, .92);
    backdrop-filter: blur(8px);
    color: var(--pt-ink-800);
    font-family: var(--pt-font-display);
    font-size: var(--pt-text-xs);
    font-weight: 700;
    letter-spacing: .02em;
    text-transform: uppercase;
}

/* -------------------------------------------------------------- stars --- */

.pt-stars { display: inline-flex; gap: 1px; color: var(--pt-lime-600); }
.pt-stars svg { width: 14px; height: 14px; fill: currentColor; stroke: none; }
.pt-stars--muted { color: var(--pt-slate-400); }
.pt-stars--lg svg { width: 18px; height: 18px; }

/* -------------------------------------------------------------- price --- */

.pt-price { display: flex; align-items: baseline; gap: .35rem; flex-wrap: wrap; }
.pt-price__label, .pt-price__value, .pt-price__unit, .pt-price__strike { display: inline-block; }

.pt-price__label {
    font-size: var(--pt-text-xs);
    color: var(--pt-text-faint);
    text-transform: uppercase;
    letter-spacing: .06em;
}

.pt-price__value {
    font-family: var(--pt-font-display);
    font-size: 1.3rem;
    font-weight: 700;
    color: var(--pt-heading);
    letter-spacing: -0.02em;
}

.pt-price__unit { font-size: var(--pt-text-xs); color: var(--pt-text-faint); }

.pt-price__strike {
    font-size: var(--pt-text-sm);
    color: var(--pt-slate-400);
    text-decoration: line-through;
}

/* --------------------------------------------------------------- grid --- */

.pt-grid { display: grid; gap: var(--pt-gap-lg); }
.pt-grid--2 { grid-template-columns: repeat(auto-fit, minmax(clamp(260px, 40%, 420px), 1fr)); }
.pt-grid--3 { grid-template-columns: repeat(auto-fill, minmax(clamp(250px, 30%, 340px), 1fr)); }
.pt-grid--4 { grid-template-columns: repeat(auto-fill, minmax(clamp(210px, 22%, 290px), 1fr)); }

/* ------------------------------------------------------------- forms ---- */

.pt-field { display: flex; flex-direction: column; gap: .3rem; }

.pt-label {
    font-family: var(--pt-font-display);
    font-size: var(--pt-text-xs);
    font-weight: 700;
    letter-spacing: .07em;
    text-transform: uppercase;
    color: var(--pt-text-faint);
}

.pt-input,
.pt-select,
.pt-textarea {
    width: 100%;
    padding: .7rem .9rem;
    border: 1px solid var(--pt-border);
    border-radius: var(--pt-radius-sm);
    background: var(--pt-paper);
    color: var(--pt-text);
    font-family: inherit;
    font-size: var(--pt-text-base);
    transition: border-color .18s var(--pt-ease), box-shadow .18s var(--pt-ease);
}

.pt-input:focus,
.pt-select:focus,
.pt-textarea:focus {
    outline: none;
    border-color: var(--pt-blue-500);
    box-shadow: var(--pt-ring);
}

.pt-textarea { min-height: 110px; resize: vertical; }

.pt-select {
    appearance: none;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%2374819A' stroke-width='2.2' stroke-linecap='round'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: right .75rem center;
    padding-right: 2.25rem;
}

/* --------------------------------------------------------- reveal ------- */

/* Paired with reveal.js. The class is added by script, never in markup, so a
   visitor with JS disabled sees the content rather than a blank page. */
.pt-reveal {
    opacity: 0;
    transform: translateY(22px);
    transition: opacity .7s var(--pt-ease-out), transform .7s var(--pt-ease-out);
}

.pt-reveal.is-visible { opacity: 1; transform: none; }

.pt-reveal[data-delay="1"] { transition-delay: .08s; }
.pt-reveal[data-delay="2"] { transition-delay: .16s; }
.pt-reveal[data-delay="3"] { transition-delay: .24s; }
.pt-reveal[data-delay="4"] { transition-delay: .32s; }
.pt-reveal[data-delay="5"] { transition-delay: .40s; }

@media (prefers-reduced-motion: reduce) {
    .pt-reveal { opacity: 1; transform: none; }
}

/* ------------------------------------------------------------ helpers --- */

.pt-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;
}

.pt-muted { color: var(--pt-text-muted); }
.pt-center { text-align: center; }

/* A wide element (table, code block, diagram) scrolls inside its own box so the
   page body never scrolls sideways. */
.pt-scroll-x { overflow-x: auto; -webkit-overflow-scrolling: touch; }

/* Horizontal snap rail used by the mobile card carousels. */
.pt-rail {
    display: grid;
    grid-auto-flow: column;
    grid-auto-columns: minmax(260px, 78vw);
    gap: var(--pt-gap);
    overflow-x: auto;
    scroll-snap-type: x mandatory;
    padding-bottom: .5rem;
    scrollbar-width: none;
}

.pt-rail::-webkit-scrollbar { display: none; }
.pt-rail > * { scroll-snap-align: start; }

@media (min-width: 900px) {
    .pt-rail {
        grid-auto-flow: row;
        grid-auto-columns: auto;
        grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
        overflow: visible;
    }
}

/* Decorative separator: a hairline that fades out from a lime seed. */
.pt-rule {
    height: 1px;
    border: 0;
    margin: 0;
    background: linear-gradient(90deg, var(--pt-lime-500), var(--pt-line) 22%, transparent);
}

/* Empty states — every listing needs one and they were all bespoke before. */
.pt-empty {
    text-align: center;
    padding: clamp(2.5rem, 6vw, 4.5rem) 1.5rem;
    background: var(--pt-paper);
    border: 1px dashed var(--pt-border);
    border-radius: var(--pt-radius-lg);
}

.pt-empty__icon {
    display: inline-grid;
    place-items: center;
    width: 60px;
    height: 60px;
    margin-bottom: var(--pt-gap);
    border-radius: 50%;
    background: var(--pt-blue-100);
    color: var(--pt-blue-600);
}

.pt-empty__icon svg { width: 26px; height: 26px; }
.pt-empty h3 { margin-bottom: .35rem; }
.pt-empty p { color: var(--pt-text-muted); margin-bottom: var(--pt-gap-lg); }

/* ============================================================================
   Bootstrap compatibility shim.

   The site no longer ships Bootstrap — the whole framework was being loaded for
   a handful of display and grid utilities plus one collapse. These are those
   utilities, reimplemented in about forty lines. Anything not listed here was
   not in use; a grep of Views turned up only these.
   ========================================================================== */

.row {
    display: flex;
    flex-wrap: wrap;
    margin-inline: -0.75rem;
}

.row > [class*="col"] { padding-inline: 0.75rem; }

.col { flex: 1 0 0%; min-width: 0; }

.d-none { display: none !important; }
.d-inline { display: inline !important; }
.d-inline-block { display: inline-block !important; }
.d-block { display: block !important; }
.d-flex { display: flex !important; }

@media (min-width: 576px) {
    .d-sm-none { display: none !important; }
    .d-sm-inline { display: inline !important; }
    .d-sm-block { display: block !important; }
    .d-sm-flex { display: flex !important; }
}

@media (min-width: 768px) {
    .d-md-none { display: none !important; }
    .d-md-inline { display: inline !important; }
    .d-md-block { display: block !important; }
    .d-md-flex { display: flex !important; }
}

@media (min-width: 992px) {
    .d-lg-none { display: none !important; }
    .d-lg-inline { display: inline !important; }
    .d-lg-block { display: block !important; }
    .d-lg-flex { display: flex !important; }
}

.text-center { text-align: center !important; }
.ms-auto { margin-left: auto !important; }
.mb-0 { margin-bottom: 0 !important; }
.mb-2 { margin-bottom: .5rem !important; }
.mb-3 { margin-bottom: 1rem !important; }
.mt-3 { margin-top: 1rem !important; }
.pb-3 { padding-bottom: 1rem !important; }

/* The legacy .btn variants a few views still carry, mapped onto the real
   button component so they cannot render unstyled. */
.btn { }
.btn-primary { }
.btn-secondary { }
.btn:not(.pt-btn) {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: .5rem;
    padding: .8rem 1.5rem;
    border: 1px solid transparent;
    border-radius: var(--pt-radius-pill);
    background: var(--pt-primary);
    color: #fff;
    font-family: var(--pt-font-display);
    font-weight: 600;
    cursor: pointer;
    transition: transform .2s var(--pt-ease), box-shadow .2s var(--pt-ease);
}

.btn:not(.pt-btn):hover { transform: translateY(-2px); box-shadow: var(--pt-shadow-lg); color: #fff; }

.btn-secondary:not(.pt-btn) {
    background: transparent;
    border-color: var(--pt-border);
    color: var(--pt-heading);
}

.btn-secondary:not(.pt-btn):hover { color: var(--pt-blue-600); border-color: var(--pt-blue-500); }

/* ------------------------------------------------------- page scaffold --- */

/* Keyboard users land on this before the nav; it stays off-screen until it
   takes focus. */
.pt-skip {
    position: absolute;
    left: -9999px;
    top: 0;
    z-index: 1000;
    padding: .75rem 1.25rem;
    background: var(--pt-ink-800);
    color: #fff;
    border-radius: 0 0 var(--pt-radius) 0;
    font-weight: 600;
}

.pt-skip:focus { left: 0; color: #fff; }

/* Interior pages: breathing room under the solid header and above the footer. */
.pt-page { padding-block: clamp(1.75rem, 4vw, 3rem) var(--pt-section-y); }

/* Page header used by every interior page that has no photographic hero. */
.pt-pagehead {
    padding-block: clamp(1.5rem, 3vw, 2.5rem);
    margin-bottom: var(--pt-gap-xl);
    border-bottom: 1px solid var(--pt-line);
}

.pt-pagehead h1 { margin-bottom: .4rem; }
.pt-pagehead p { color: var(--pt-text-muted); margin: 0; max-width: 44rem; }

/* Breadcrumbs — small, quiet, and the same on every page that has them. */
.pt-crumbs {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: .35rem;
    margin-bottom: .75rem;
    font-size: var(--pt-text-xs);
    color: var(--pt-text-faint);
}

.pt-crumbs a { color: var(--pt-text-faint); }
.pt-crumbs a:hover { color: var(--pt-blue-600); }
.pt-crumbs span[aria-current] { color: var(--pt-slate-700); font-weight: 600; }
.pt-crumbs svg { width: 12px; height: 12px; opacity: .6; }

/* Unfilled stars keep their outline so a low rating still reads as a rating
   rather than as missing content. */
.pt-stars svg.is-empty { fill: none; stroke: currentColor; stroke-width: 1.6; opacity: .3; }
