/* static/css/composition.css
 *
 * Composition + utility layer for chempirical.
 * Pure additions — does NOT replace base.css or tailwind.css. Existing
 * pages keep working until templates are migrated to these classes.
 *
 * Naming convention: `cmp-*` so a grep tells you immediately which
 * design language a class belongs to.
 *
 * Reference values (Linear, dark theme):
 *   body         16/24, -0.011em
 *   h1 hero      64 / 600 / lh 1.0 / tracking -0.022em
 *   h2 section   48 / 600 / lh 1.0 / tracking -0.022em
 *   h3 card      20 / 590 / lh 1.33 / tracking -0.012em
 *   eyebrow      12 mono uppercase, muted
 *   pill button  9999 radius, h32, 13/510, inverted
 */


/* ---------- Body baseline ---------- */

/* Slight negative tracking globally — closest visual match to Inter at
   Linear's settings. Does not change vertical rhythm.
   overflow-x: clip on both html and body suppresses horizontal scroll
   from absolutely-positioned panels (e.g. the desktop tools dropdown)
   that would otherwise extend past viewport at tablet widths. */
html {
    overflow-x: clip;
}
body {
    letter-spacing: -0.011em;
    overflow-x: clip;
}


/* ---------- Focus indicator ---------- */

/* Tailwind's preflight strips the default browser outline. Apply a
   visible primary-tinted ring on every cmp-* interactive surface so
   keyboard nav stays usable. Uses :focus-visible so mouse clicks
   don't paint a halo. */
.cmp-pill-button:focus-visible,
.cmp-pill-button-ghost:focus-visible,
.cmp-card:focus-visible,
.cmp-tool-card:focus-visible,
.cmp-feature-card:focus-visible,
.cmp-section-link:focus-visible {
    outline: 2px solid hsl(var(--primary));
    outline-offset: 2px;
    border-radius: inherit;
}

.cmp-pill-button:focus-visible {
    outline-offset: 3px;
}


/* ---------- Display headings ---------- */

.cmp-display-h1 {
    font-size: clamp(2.5rem, 6vw + 1rem, 4rem);  /* 40px → 64px */
    font-weight: 600;
    line-height: 1.05;
    letter-spacing: -0.022em;
    color: hsl(var(--foreground));
    margin: 0;
}

.cmp-display-h2 {
    font-size: clamp(2rem, 4vw + 0.75rem, 3rem);  /* 32px → 48px */
    font-weight: 600;
    line-height: 1.05;
    letter-spacing: -0.022em;
    color: hsl(var(--foreground));
    margin: 0;
}

.cmp-display-h3 {
    font-size: 1.25rem;        /* 20px */
    font-weight: 590;
    line-height: 1.33;
    letter-spacing: -0.012em;
    color: hsl(var(--foreground));
    margin: 0;
}

/* Display lead paragraph next to a hero h1 */
.cmp-lead {
    font-size: 1.125rem;       /* 18px */
    line-height: 1.55;
    color: hsl(var(--muted-foreground));
    letter-spacing: -0.011em;
    max-width: 38ch;
    margin: 0;
}


/* ---------- Eyebrow ---------- */

/* Small label that sits above a section heading. Replaces the
   "CHEMINFORMATICS SUITE" treatment in the old hero.
   Uses the theme primary as a *subtle* accent — still small/muted
   so it whispers rather than shouts, but ties pages back to brand.
   Sans-serif (inherits from body) so eyebrows don't look like terminal
   output — the mono font is reserved for code-like content (formulas,
   kbd hints, CAS numbers). */
.cmp-eyebrow {
    font-size: 0.75rem;        /* 12px */
    font-weight: 600;
    line-height: 1.5;
    letter-spacing: 0.1em;     /* a touch wider since uppercase + sans needs more air */
    text-transform: uppercase;
    color: hsl(var(--primary));
    margin: 0 0 0.875rem 0;
}

/* Variant for places where primary would clash (e.g. inside a card
   that already uses primary). Falls back to muted. */
.cmp-eyebrow-muted {
    color: hsl(var(--muted-foreground));
}


/* ---------- Pill button ---------- */

/* Inverted primary CTA: light bg + dark text on a dark page,
   dark bg + light text on a light page. Linear's hero button. */
.cmp-pill-button {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    height: 2rem;              /* 32px */
    padding: 0 0.75rem;        /* 12px */
    border-radius: 9999px;
    font-size: 0.8125rem;      /* 13px */
    font-weight: 510;
    line-height: 1;
    letter-spacing: -0.005em;
    background: hsl(var(--foreground));
    color: hsl(var(--background));
    border: 1px solid transparent;
    text-decoration: none;
    white-space: nowrap;
    transition: opacity 150ms ease, transform 150ms ease;
}

.cmp-pill-button:hover {
    opacity: 0.9;
}

.cmp-pill-button:active {
    transform: translateY(1px);
}

/* Ghost variant — outlined, sits next to the primary pill. */
.cmp-pill-button-ghost {
    background: transparent;
    color: hsl(var(--foreground));
    border-color: hsl(var(--border));
}

.cmp-pill-button-ghost:hover {
    background: hsl(var(--muted) / 0.5);
    opacity: 1;
}


/* ---------- Sections ---------- */

/* Linear's homepage uses ~72px between top-level page sections, with
   inner content max-width that lives on the grid, not on <main>. */
.cmp-section {
    margin-top: 4.5rem;        /* 72px */
}

.cmp-section:first-child {
    margin-top: 0;
}

.cmp-section-head {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: 0.75rem;
    margin-bottom: 1.5rem;
}

/* Subtle tertiary link, sits at the right edge of a section head.
   Primary on hover — small accent moment without shouting. */
.cmp-section-link {
    font-size: 0.8125rem;
    color: hsl(var(--muted-foreground));
    text-decoration: none;
    transition: color 150ms ease;
}

.cmp-section-link:hover {
    color: hsl(var(--primary));
}


/* ---------- Card register ---------- */

/* Featured-molecule card. Horizontal layout on desktop: square SVG
   visual on the left, vertical divider, prose body on the right. One
   card per row — gives the long descriptions room to breathe instead
   of forcing them into a 220px column with line-clamp. Falls back to
   stacked column layout on mobile. */
.cmp-card {
    position: relative;
    display: grid;
    grid-template-columns: minmax(180px, 220px) 1fr;
    gap: 1.75rem;
    padding: 1.5rem 0;
    color: inherit;
    text-decoration: none;
    border-top: 1px solid hsl(var(--border) / 0.4);
    transition: background-color 200ms ease;
}

.cmp-card:first-of-type {
    border-top: 0;
    padding-top: 0.5rem;
}

.cmp-card:hover {
    background: hsl(var(--muted) / 0.15);
}

.cmp-card-body {
    /* Subtle vertical divider on the left side — visually separates
       the visual from the prose without adding DOM.
       flex-column lets the reference link below stick to the bottom
       of the card via margin-top: auto, regardless of how long the
       blurb above happens to be. */
    display: flex;
    flex-direction: column;
    padding-left: 1.75rem;
    border-left: 1px solid hsl(var(--border) / 0.4);
}

@media (max-width: 640px) {
    .cmp-card {
        grid-template-columns: 1fr;
        gap: 0.875rem;
    }
    .cmp-card-body {
        padding-left: 0;
        border-left: 0;
    }
}

/* Stretched-link pattern: the title is the primary <a>, but its
   ::after pseudo extends across the whole card so any click in dead
   space hits this link. */
.cmp-card-stretched-link {
    color: inherit;
    text-decoration: none;
}

.cmp-card-stretched-link::after {
    content: '';
    position: absolute;
    inset: 0;
    z-index: 1;
}

.cmp-card-stretched-link:focus-visible {
    outline: none;
}

.cmp-card-stretched-link:focus-visible::after {
    outline: 2px solid hsl(var(--primary));
    outline-offset: 2px;
    border-radius: 0.625rem;
}

/* Visual slot — square aspect by default, override via inline style or
   modifier. Slight bg so empty slots don't disappear, very subtle border. */
.cmp-card-visual {
    position: relative;
    width: 100%;
    aspect-ratio: 1 / 1;
    overflow: hidden;
    border-radius: 0.625rem;   /* 10px */
    background: hsl(var(--muted) / 0.4);
    border: 1px solid hsl(var(--border) / 0.5);
    transition: border-color 200ms ease, background-color 200ms ease;
    display: flex;
    align-items: center;
    justify-content: center;
}

.cmp-card:hover .cmp-card-visual {
    border-color: hsl(var(--primary) / 0.4);
    background: hsl(var(--muted) / 0.6);
}

.cmp-card-visual > svg,
.cmp-card-visual > img {
    max-width: 75%;
    max-height: 75%;
    width: auto;
    height: auto;
    display: block;
}

/* Card text block — title + one-line description, tight stack. */
.cmp-card-body > * + * {
    margin-top: 0.25rem;       /* 4px between title and description */
}

.cmp-card-title {
    font-size: 1.375rem;       /* 22px — promoted now that each card has its own row */
    font-weight: 600;
    line-height: 1.25;
    letter-spacing: -0.018em;
    color: hsl(var(--foreground));
}

.cmp-card-desc {
    font-size: 0.8125rem;      /* 13px */
    line-height: 1.45;
    color: hsl(var(--muted-foreground));
    letter-spacing: -0.005em;
}

/* Trailing CAS / metadata after a formula in a card description.
   Stays at full muted-foreground so contrast holds AA — visual
   hierarchy comes from the mono <code> formula being denser, not
   from dimming the CAS. */
.cmp-cas-tail {
    color: hsl(var(--muted-foreground));
}

/* Multi-line blurb under formula/CAS on a featured molecule card.
   Reads as body prose now that each card has its own row — full width,
   no line-clamp. The 0.9375rem step-up over the formula/CAS desc keeps
   the visual hierarchy: title (22) > blurb (15) > formula/CAS (13). */
.cmp-card-blurb {
    margin-top: 0.625rem;
    font-size: 0.9375rem;
    line-height: 1.55;
    color: hsl(var(--foreground) / 0.82);
    letter-spacing: -0.006em;
}

/* References block — sits above the stretched ::after via z-index.
   margin-top: auto on the wrapper pushes it to the bottom of the
   flex-column card body so all rows align horizontally regardless of
   blurb length. */
.cmp-card-refs {
    position: relative;
    z-index: 2;
    margin-top: auto;
    padding-top: 1rem;          /* breathing room from the blurb above */
    display: flex;
    flex-direction: column;
    gap: 0.25rem;
    align-items: flex-start;
}

.cmp-card-ref {
    display: inline-flex;
    align-items: center;
    font-size: 0.75rem;
    color: hsl(var(--primary));
    text-decoration: none;
    transition: opacity 150ms ease;
}

.cmp-card-ref:hover {
    opacity: 0.8;
    text-decoration: underline;
}


/* ---------- Tool card variant (icon, no aspect lock) ---------- */

/* A tool card has an icon, not a square image — so the visual collapses
   to a small icon row above the title. */
.cmp-tool-card {
    display: flex;
    flex-direction: column;
    gap: 0.625rem;
    color: inherit;
    text-decoration: none;
    padding: 1.25rem;
    border-radius: 0.75rem;
    border: 1px solid hsl(var(--border) / 0.5);
    background: transparent;
    transition: border-color 200ms ease, background-color 200ms ease,
                transform 200ms ease;
}

.cmp-tool-card:hover {
    border-color: hsl(var(--primary) / 0.4);
    background: hsl(var(--muted) / 0.3);
    transform: translateY(-1px);
}

.cmp-tool-card-icon {
    width: 2rem;
    height: 2rem;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    color: hsl(var(--foreground) / 0.85);
}

.cmp-tool-card-icon > svg {
    width: 100%;
    height: 100%;
}


/* ---------- Feature card (Linear PageSection-ish) ---------- */

/* Bigger, breathier tool/feature card for the homepage. Larger icon
   slot on the left, eyebrow + title + lead + CTA stacked on the right.
   Two columns at desktop, single column at mobile. Subtle hover
   accent in primary so the green pulse appears throughout the page. */
.cmp-feature-card {
    display: grid;
    grid-template-columns: minmax(120px, 160px) 1fr;
    gap: 1.5rem;
    padding: 1.75rem 1.5rem;
    border-radius: 0.875rem;
    border: 1px solid hsl(var(--border) / 0.5);
    background: transparent;
    color: inherit;
    text-decoration: none;
    transition: border-color 200ms ease, background-color 200ms ease,
                transform 200ms ease;
    align-items: start;
}

.cmp-feature-card:hover {
    border-color: hsl(var(--primary) / 0.45);
    background: hsl(var(--muted) / 0.25);
    transform: translateY(-2px);
}

.cmp-feature-card-visual {
    display: flex;
    align-items: center;
    justify-content: center;
    aspect-ratio: 1 / 1;
    width: 100%;
    border-radius: 0.625rem;
    background: hsl(var(--muted) / 0.4);
    color: hsl(var(--primary));
    border: 1px solid hsl(var(--border) / 0.5);
    transition: border-color 200ms ease, background-color 200ms ease;
}

.cmp-feature-card:hover .cmp-feature-card-visual {
    border-color: hsl(var(--primary) / 0.45);
    background: hsl(var(--primary) / 0.08);
}

.cmp-feature-card-visual > svg {
    width: 48%;
    height: 48%;
    color: inherit;
}

.cmp-feature-card-body {
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
    min-width: 0;
}

.cmp-feature-card-title {
    font-size: 1.25rem;        /* 20px */
    font-weight: 590;
    line-height: 1.25;
    letter-spacing: -0.012em;
    color: hsl(var(--foreground));
    margin: 0;
}

.cmp-feature-card-desc {
    font-size: 0.9375rem;      /* 15px */
    line-height: 1.5;
    color: hsl(var(--muted-foreground));
    letter-spacing: -0.005em;
    margin: 0;
}

.cmp-feature-card-cta {
    display: inline-flex;
    align-items: center;
    gap: 0.25rem;
    margin-top: 0.25rem;
    font-size: 0.8125rem;
    font-weight: 510;
    color: hsl(var(--primary));
    transition: gap 150ms ease;
}

.cmp-feature-card:hover .cmp-feature-card-cta {
    gap: 0.5rem;
}

@media (max-width: 480px) {
    .cmp-feature-card {
        grid-template-columns: 80px 1fr;
        gap: 1rem;
        padding: 1.25rem;
    }
    .cmp-feature-card-title {
        font-size: 1.125rem;
    }
}


/* Two-column auto grid for feature cards. Drops to one column under 720px. */
.cmp-grid-features {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 1rem;
}

@media (max-width: 720px) {
    .cmp-grid-features {
        grid-template-columns: 1fr;
    }
}


/* ---------- Grid ---------- */

/* Single-column layout for featured-molecule cards. Each card is a
   full-width horizontal row (square visual + prose body) — the gap
   between rows comes from the cmp-card top border + padding so this
   grid only needs to stack them vertically. */
.cmp-grid {
    display: grid;
    grid-template-columns: 1fr;
    gap: 0;
}

.cmp-grid-tools {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
    gap: 1rem;
}


/* ---------- Search field ---------- */

/* Linear-clean search row: subtle muted background, leading icon,
   trailing kbd hint, suggestions dropdown styled to match. Sits inside
   the hero or any section. Whole thing is a form so Enter submits. */
.cmp-search {
    width: 100%;
    max-width: 36rem;          /* 576px — same airy width as hero text */
    margin-top: 1.75rem;
}

.cmp-search-form {
    position: relative;
    display: flex;
    align-items: center;
    gap: 0.625rem;
    height: 2.75rem;            /* 44px */
    padding: 0 0.75rem 0 1rem;
    border-radius: 0.625rem;    /* 10px */
    background: hsl(var(--muted) / 0.4);
    border: 1px solid hsl(var(--border) / 0.6);
    transition: border-color 150ms ease, background-color 150ms ease;
}

.cmp-search-form:focus-within {
    border-color: hsl(var(--primary) / 0.5);
    background: hsl(var(--muted) / 0.55);
}

.cmp-search-icon {
    flex: none;
    display: inline-flex;
    align-items: center;
    color: hsl(var(--muted-foreground));
    pointer-events: none;
}

.cmp-search-form:focus-within .cmp-search-icon {
    color: hsl(var(--primary));
}

.cmp-search-input {
    flex: 1 1 auto;
    min-width: 0;
    height: 100%;
    border: 0;
    outline: 0;
    background: transparent;
    color: hsl(var(--foreground));
    font-size: 0.9375rem;       /* 15px */
    letter-spacing: -0.005em;
    font-family: inherit;
}

.cmp-search-input::placeholder {
    color: hsl(var(--muted-foreground));
    font-size: 0.875rem;
    letter-spacing: -0.005em;
    opacity: 0.85;
}

/* Hide the native search-clear button so the kbd hint stays visible */
.cmp-search-input::-webkit-search-cancel-button { display: none; }

/* Clear (X) button — only visible when the input has content. CSS-only
   visibility toggle via :placeholder-shown so we don't need JS to flip
   classes on every keystroke. tabindex="-1" in HTML keeps it out of the
   tab order; click handler does the actual clear. */
.cmp-search-clear {
    flex: none;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 1.5rem;
    height: 1.5rem;
    padding: 0;
    border: 0;
    border-radius: 9999px;
    background: hsl(var(--muted) / 0.6);
    color: hsl(var(--muted-foreground));
    cursor: pointer;
    transition: background-color 150ms ease, color 150ms ease;
}

.cmp-search-clear:hover {
    background: hsl(var(--muted));
    color: hsl(var(--foreground));
}

.cmp-search-input:placeholder-shown ~ .cmp-search-clear {
    display: none;
}

/* Kbd-shaped Enter/submit button. Real <button type="submit"> so click
   AND Enter both submit the form. Sized like a keyboard hint, with a
   primary tint on hover to signal it's interactive. */
.cmp-search-kbd {
    flex: none;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    height: 1.5rem;
    min-width: 1.75rem;
    padding: 0 0.4rem;
    border: 1px solid hsl(var(--border));
    border-radius: 0.3rem;
    background: hsl(var(--background));
    color: hsl(var(--muted-foreground));
    font-family: inherit;
    font-size: 0.875rem;
    line-height: 1;
    cursor: pointer;
    transition: border-color 150ms ease, background-color 150ms ease, color 150ms ease;
}

.cmp-search-kbd:hover {
    border-color: hsl(var(--primary) / 0.5);
    background: hsl(var(--primary) / 0.1);
    color: hsl(var(--primary));
}

.cmp-search-icon, .cmp-search-input, .cmp-search-clear, .cmp-search-kbd {
    position: relative;
    z-index: 1;
}

/* Suggestions dropdown — flat, no card chrome, primary border accent */
.cmp-search-suggestions {
    position: absolute;
    z-index: 50;
    top: calc(100% + 0.5rem);
    left: 0;
    right: 0;
    max-height: 22rem;
    overflow-y: auto;
    padding: 0.5rem 0;
    border-radius: 0.625rem;
    border: 1px solid hsl(var(--border));
    background: hsl(var(--background));
    box-shadow: 0 12px 32px -8px hsl(0 0% 0% / 0.4);
    text-align: left;
}


/* ---------- Hero block ---------- */

/* Linear hero: edge-to-edge, large heading, generous vertical padding,
   no background gimmicks (no acrylic, no noise, no radial glow). */
.cmp-hero {
    padding-top: 6rem;          /* 96px */
    padding-bottom: 4.5rem;     /* 72px */
    text-align: left;
    max-width: 64rem;
}

.cmp-hero-actions {
    display: flex;
    flex-wrap: wrap;
    gap: 0.75rem;
    margin-top: 2rem;
}

@media (max-width: 640px) {
    .cmp-hero {
        padding-top: 3rem;
        padding-bottom: 3rem;
    }
}


/* ---------- Stat strip (used on the homepage) ---------- */

/* Linear-style numeric strip — tabular numerals, foreground-color text,
   no card chrome. */
.cmp-stat-strip {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
    gap: 2rem;
    padding-top: 2rem;
    border-top: 1px solid hsl(var(--primary) / 0.25);
}

.cmp-stat-value {
    font-size: 2.25rem;        /* 36px */
    font-weight: 600;
    line-height: 1.1;
    letter-spacing: -0.022em;
    font-variant-numeric: tabular-nums;
    color: hsl(var(--foreground));
}

.cmp-stat-label {
    margin-top: 0.25rem;
    font-size: 0.8125rem;      /* 13px */
    color: hsl(var(--muted-foreground));
}
