/* ===========================================================
   UNAMIQ - components
   Reusable pieces: buttons, section labels, the founders grid,
   the projects list, project detail blocks and the contact form.

   A component is anything that could appear on more than one
   page. If it genuinely only ever appears once, it belongs in
   css/pages/<that-page>.css instead.
=========================================================== */

.cta-button{
    display:inline-block;
    text-decoration:none;

    border:1px solid var(--cta-border);
    color:var(--cta-color);

    font-family:"Space Grotesk", sans-serif;
    font-weight:700;
    font-size:var(--fs-sm);
    letter-spacing:.12em;
    text-transform:uppercase;

    padding:13px 30px;

    transition:background-color .3s ease, color .3s ease, border-color .3s ease, transform .3s cubic-bezier(.2,.8,.2,1);
}

.cta-button:hover{
    background-color:var(--cta-hover-bg);
    color:var(--cta-hover-color);
    border-color:var(--cta-hover-bg);
    transform:translateY(-2px);
}

.footer-contact{
    margin-right:8px;
}

@media(max-width:700px){
    .footer-contact{ margin-right:0; margin-bottom:18px;
    }
}

/* Used on About and Capabilities. This lived in pages/about.css,
   which Capabilities does not load — so "No Prototype, No Meeting"
   rendered at the browser's default h2 (24px, no caps, no tracking)
   while About's got 2.3rem uppercase. Same class, two appearances.
   It is shared, so it belongs here. */
.section-heading{
    font-size:clamp(1.6rem, 3.6vw, 2.3rem);
    font-weight:700;
    letter-spacing:.04em;
    text-transform:uppercase;
    margin-bottom:44px;
}

.section-label{
    font-family:"Space Mono", monospace;
    
    font-weight:400;
    font-size:var(--fs-xs);
    letter-spacing:.25em;
    text-transform:uppercase;
    color:var(--accent-ink, rgba(255,255,255,.75));
    margin-bottom:18px;
}

/* ===========================================================
   FRAMED MEDIA — one behaviour for every picture on the site

   This was eleven near-identical copies across six files, which
   is how /capabilities ended up with process images that had no
   hover at all while everything around them did.

   At rest a frame is anchored by a faint accent line and an
   equally faint all-round glow; without them a photograph on a
   near-white page floats. On hover both become definite and the
   frame grows by --media-scale.

   WHERE THE GROWTH HAPPENS: a frame inside a card scales WITH the
   card, so the picture and the text under it grow together and
   the frame itself only lights up. The founder cards on /about
   are the reference. A frame standing alone scales itself.

   NOT INCLUDED: .bg-layer on the home page — full-bleed
   background renders, nothing to frame and nothing to hover.
=========================================================== */

.founder-photo,
.about-photo,
.details-image,
.project-hero-image,
.project-video,
.project-media,
.project-split-media,
.project-photo,
.project-card-media,
.process-image{
    overflow:hidden;

    border:1px solid var(--media-border);
    box-shadow:var(--media-shadow);

    transition:transform .4s cubic-bezier(.2,.8,.2,1),
               border-color .35s ease,
               box-shadow .35s ease;
}

/* ---- frames that stand on their own: they scale themselves ---- */
.about-photo:hover,
.project-hero-image:hover,
.project-video:hover,
.project-media:hover,
.project-split-media:hover,
.project-photo:hover{
    transform:scale(var(--media-scale));
    border-color:var(--media-border-hover);
    box-shadow:var(--media-shadow-hover);
}

/* ---- frames inside a card: the card scales, the frame lights up ---- */
.founder-card,
.project-card,
.process-card{
    transition:transform .4s cubic-bezier(.2,.8,.2,1);
}

.founder-card:hover,
.project-card:hover,
.project-card:focus-visible,
.process-card:hover{
    transform:scale(var(--media-scale));
}

.founder-card:hover .founder-photo,
.project-card:hover .project-card-media,
.project-card:focus-visible .project-card-media,
.process-card:hover .process-image,
.project-item:hover .details-image,
.project-item:focus-within .details-image{
    border-color:var(--media-border-hover);
    box-shadow:var(--media-shadow-hover);
}


.founders-grid{
    display:grid;
    grid-template-columns:repeat(4, 1fr);
    gap:36px;
}

.founder-card{
    cursor:default;
}

.founder-photo{
    aspect-ratio:4 / 5;
    margin-bottom:22px;

    display:flex;
    align-items:center;
    justify-content:center;

    background:linear-gradient(160deg, var(--bg-alt, rgba(255,255,255,.07)), transparent);
}

.founder-photo img{
    width:100%;
    height:100%;
    object-fit:cover;
    display:block;
}

.founder-photo .initials{
    font-family:"Space Grotesk", sans-serif;
    font-size:2.4rem;
    font-weight:700;
    letter-spacing:.04em;
    color:var(--text-faintest, rgba(255,255,255,.16));
}

.founder-name{
    font-size:var(--fs-md);
    font-weight:700;
    letter-spacing:.06em;
    text-transform:uppercase;
    margin-bottom:8px;
}

.founder-bio{
    font-size:var(--fs-base);
    line-height:1.55;
    color:var(--text-muted, rgba(255,255,255,.5));
}

@media(max-width:900px){
    .founders-grid{ grid-template-columns:repeat(2, 1fr); gap:40px 28px;
    }
}

@media(max-width:520px){
    .founders-grid{ grid-template-columns:1fr;
    }
}

.projects-list{
    display:flex;
    flex-direction:column;
    border-top:1px solid var(--border-color, rgba(255,255,255,.1));
}

.project-item{
    display:block;
    text-decoration:none;
    color:inherit;

    border-bottom:1px solid var(--border-color, rgba(255,255,255,.1));
    transition:background-color .35s ease;
}

.project-item:hover{
    background-color:var(--card-bg-hover, rgba(255,255,255,.03));
}

.project-row{
    display:flex;
    align-items:baseline;
    gap:28px;

    padding:38px 0;
}

.project-index{
    font-family:"Space Mono", monospace;
    font-size:var(--fs-sm);
    color:var(--text-faint, rgba(255,255,255,.35));
    width:44px;
    flex-shrink:0;
}

.project-name{
    flex:1;
    font-size:clamp(1.3rem, 3.2vw, 2.1rem);
    font-weight:700;
    letter-spacing:.03em;
    text-transform:uppercase;
}

.project-status{
    font-family:"Space Mono", monospace;
    font-size:var(--fs-xs);
    letter-spacing:.1em;
    text-transform:uppercase;
    color:var(--text-faint, rgba(255,255,255,.4));
    white-space:nowrap;
}

.project-item.tba .project-name{
    color:var(--text-faint, rgba(255,255,255,.46));
}

.project-item.tba .project-status{
    color:var(--text-faint, rgba(255,255,255,.46));
}

.project-details{
    display:grid;
    grid-template-rows:0fr;
    transition:grid-template-rows .55s cubic-bezier(.2,.8,.2,1);
}

.project-item:hover .project-details,
.project-item:focus-within .project-details{
    grid-template-rows:1fr;
}

.details-inner{
    overflow:hidden;
}

.details-content{
    display:flex;
    gap:44px;
    align-items:flex-start;

    
    margin-left:72px;

    padding-bottom:48px;

    opacity:0;
    transform:translateY(8px);
    transition:opacity .4s ease .05s, transform .4s ease .05s;
}

.project-item:hover .details-content,
.project-item:focus-within .details-content{
    opacity:1;
    transform:translateY(0);
}

.details-image{
    flex:0 0 460px;
    aspect-ratio:16 / 10;
}

/* Only paint a background when the slot holds a real image; a
   placeholder keeps the shared .placeholder-box gradient. */
.details-image:not(.placeholder-box){
    background:var(--bg-alt, rgba(255,255,255,.04));
}

.details-image img{
    width:100%;
    height:100%;
    object-fit:cover;
    display:block;
}

.details-text{
    flex:1;
    font-size:var(--fs-md);
    line-height:1.7;
    color:var(--text-muted, rgba(255,255,255,.6));
    max-width:520px;
}

@media(max-width:760px){
    .details-content{
        flex-direction:column;
        gap:24px;
        margin-left:0;
    }

    .details-image{
        flex-basis:auto;
        width:100%;
    }
}

@media(max-width:600px){
    .project-row{
        padding:26px 0;
        gap:16px;
        flex-wrap:wrap;
        row-gap:10px;
    }

    .project-index{ width:28px;
    }

    .project-name{
        flex:1 1 auto;
        min-width:0;
        overflow-wrap:anywhere;
    }

    .project-status{
        flex:0 0 100%;
        padding-left:44px;
    }
}

.project-hero-image{
    width:100%;
    aspect-ratio:16 / 9;
    margin-bottom:52px;
}

/* Background only when it holds a real image; a placeholder keeps
   the shared .placeholder-box gradient. */
.project-hero-image:not(.placeholder-box){
    background:var(--bg-alt, rgba(255,255,255,.04));
}

.project-hero-image img{
    width:100%;
    height:100%;
    object-fit:cover;
    display:block;
}

.project-body{
    max-width:720px;
    display:flex;
    flex-direction:column;
    gap:22px;
}

.body-copy{
    font-size:var(--fs-md);
    line-height:1.75;
    color:var(--text-muted, rgba(255,255,255,.6));
}

.spec-list{
    margin-top:18px;
    border-top:1px solid var(--border-color, rgba(255,255,255,.1));
}

.spec-row{
    display:flex;
    justify-content:space-between;
    gap:24px;

    padding:16px 0;
    border-bottom:1px solid var(--border-color, rgba(255,255,255,.1));
}

.spec-label{
    font-family:"Space Mono", monospace;
    font-size:var(--fs-xs);
    letter-spacing:.08em;
    text-transform:uppercase;
    color:var(--text-faint, rgba(255,255,255,.4));
    white-space:nowrap;
}

.spec-value{
    font-size:var(--fs-base);
    color:var(--text-strong, rgba(255,255,255,.75));
    text-align:right;
}


/* ===========================================================
   PROJECT CARD
   One announced project, as a single link: image, title, subtitle.
   Used on Capabilities and rendered in the style guide, which is
   why it is here and not in pages/capabilities.css — it was there
   until 2026-08-31, and the style guide's copy of it rendered
   completely unstyled because that page does not load that file.
=========================================================== */

.project-cards{
    display:grid;
    grid-template-columns:1fr 1fr;
    gap:26px;
}

.project-card{
    display:block;
    text-decoration:none;
    color:inherit;
}

.project-card-media{
    aspect-ratio:16 / 9;

}

/* Background only when the card holds a real image; a placeholder
   keeps the shared .placeholder-box gradient. */
.project-card-media:not(.placeholder-box){
    background:var(--card-bg-hover, rgba(255,255,255,.03));
}

.project-card-media img{
    width:100%;
    height:100%;
    object-fit:cover;
    display:block;
}

/* The title and subtitle sit under the image rather than over it.
   A scrim caption on a photograph reads as a label; a heading
   under it reads as a link, which is what these are now. */
.project-card-text{
    padding-top:18px;
}

.project-card-title{
    font-size:var(--fs-lg);
    font-weight:700;
    letter-spacing:.05em;
    text-transform:uppercase;
    margin-bottom:8px;

    transition:color .3s ease;
}

.project-card:hover .project-card-title{
    color:var(--accent-ink);
}

.project-card-sub{
    font-family:"Space Mono", monospace;
    font-size:var(--fs-xs);
    letter-spacing:.12em;
    text-transform:uppercase;
    color:var(--text-muted, rgba(255,255,255,.56));
}

@media(max-width:760px){

    .project-cards{
        grid-template-columns:1fr;
        gap:34px;
    }

}

/* ===========================================================
   PROJECT PAGE TEMPLATE

   Every project page is built from the same blocks, in the same
   order, so two project pages never drift apart:

     .section-label       PROJECT 0n
     h1.page-heading      the project name
     .project-hero-image  the big header picture
     .project-body        intro copy + .spec-list (Status / Focus /
                          Autonomy) — the three facts every project
                          states
     .project-section     every titled block after that: milestones,
                          an innovation, next steps

   Inside a .project-section you can use any of:
     .project-video       a 16:9 slot for a self-hosted video
     .project-media-row   three images across
     .project-split       text on the left, one big image on the right

   The full copy-paste skeleton is docs/templates/project-page.php.
   The recipe is handbook §4.9.

   These live in components.css rather than a page stylesheet
   because more than one page uses them — which is the rule this
   file opens with.
=========================================================== */

.project-section{
    margin-top:88px;
    max-width:none;
}

/* .section-heading carries the size; a project section just needs
   less air beneath it than a page-level one. */
.project-section > .section-heading{
    margin-bottom:28px;
}

.project-subheading{
    font-size:var(--fs-lg);
    font-weight:700;
    letter-spacing:.05em;
    text-transform:uppercase;
    margin-bottom:20px;
}

/* Copy inside a project section keeps the same measure as the
   intro body, so the page has one reading width throughout. */
.project-section .body-copy{
    max-width:720px;
}

.project-section .body-copy + .body-copy{
    margin-top:22px;
}

:root{
    /* The tint painted behind a cut-out render. Ink at 3.5% in the light
       theme and white at 2.5% in the dark one - the same wash a card gets
       on hover - so it follows the theme without a second rule. */
    --cutout-tint: var(--card-bg-hover, rgba(0, 0, 0, .035));
}

/* ---------- video slot ----------
   Self-hosted only. An embed from YouTube or Vimeo is a
   third-party request: it would need a consent banner and the
   Content-Security-Policy in .htaccess blocks it anyway.
   See docs/decisions/adr-0002-no-third-parties.md. */
.project-video{
    width:100%;
    aspect-ratio:16 / 9;
    margin-bottom:36px;
}

.project-video:not(.placeholder-box){
    background:var(--bg-alt, rgba(255,255,255,.04));
}

/* contain, not cover: the poster is a cut-out render, and a video is
   letterboxed by the browser anyway when its ratio differs. The tint
   sits behind both, so the empty band reads as part of the frame.

   The iframe selector that used to be here has gone: an embed is a
   third-party request, which the Content-Security-Policy in .htaccess
   blocks and which would put a consent banner back on the site. */
.project-video video{
    width:100%;
    height:100%;
    display:block;
    border:0;
    object-fit:contain;
    background:var(--cutout-tint);
}

/* ---------- three images across ---------- */

.project-media-row{
    display:grid;
    grid-template-columns:repeat(3, 1fr);
    gap:18px;
    margin-bottom:36px;
}

.project-media{
    aspect-ratio:4 / 3;
}

/* A media cell paints its own background only when it holds a real
   image. A placeholder keeps the shared .placeholder-box gradient. */
.project-media:not(.placeholder-box){
    background:var(--bg-alt, rgba(255,255,255,.04));
}

.project-media img{
    width:100%;
    height:100%;
    object-fit:cover;
    display:block;
}

/* ---------- text left, one big image right ---------- */

.project-split{
    display:grid;
    grid-template-columns:minmax(0, 1fr) minmax(0, 1.15fr);
    gap:52px;
    align-items:start;
}

.project-split-body .body-copy{
    max-width:none;
}

.project-split-body .body-copy + .body-copy{
    margin-top:22px;
}

.project-split-media{
    aspect-ratio:4 / 3;
}

.project-split-media:not(.placeholder-box){
    background:var(--bg-alt, rgba(255,255,255,.04));
}

.project-split-media img{
    width:100%;
    height:100%;
    object-fit:cover;
    display:block;
}

/* ---------- cut-out renders ----------
   Some supplied images are product renders on a transparent background
   rather than photographs. Dropped straight onto the page they float
   with nothing behind them and read as a mistake, so the frame paints
   the tint and the render is CONTAINED rather than cropped - cropping a
   cut-out slices the object in half.

   This block sits AFTER the frames it modifies on purpose: they set
   their own background and object-fit at the same specificity, so
   whichever comes last wins. */
.project-media.is-cutout,
.project-split-media.is-cutout,
.project-hero-image.is-cutout{
    background:var(--cutout-tint);
}

.is-cutout img{
    object-fit:contain;
}

@media(max-width:900px){

    .project-split{
        grid-template-columns:1fr;
        gap:28px;
    }

    /* Image below the text on a narrow screen, which is the
       reading order the markup already has. */
    .project-media-row{
        grid-template-columns:1fr 1fr;
    }

}

@media(max-width:560px){

    .project-media-row{
        grid-template-columns:1fr;
    }

    .project-section{
        margin-top:64px;
    }

}

.footer-right a:not(.cta-button){
    display:flex;
    align-items:center;
    justify-content:center;
    
    width:44px;
    height:44px;
    margin:-12px;
    color:var(--text-muted, rgba(255,255,255,.6));
    transition:color .3s ease, transform .3s cubic-bezier(.2,.8,.2,1);
}

.footer-right a:not(.cta-button):hover{
    color:var(--footer-link-hover, rgba(255,255,255,1));
    transform:scale(1.15);
}

.contact-form{
    max-width:540px;
    display:flex;
    flex-direction:column;
    gap:30px;
}

.form-field{
    display:flex;
    flex-direction:column;
    gap:10px;
}

.form-field label{
    font-family:"Space Mono", monospace;
    font-size:var(--fs-xs);
    letter-spacing:.12em;
    text-transform:uppercase;
    color:var(--footer-muted, rgba(255,255,255,.45));
}

.form-field input,
.form-field textarea{
    background:transparent;
    border:none;
    border-bottom:1px solid var(--border-strong, rgba(255,255,255,.25));

    color:var(--text, white);
    font-family:"Space Grotesk", sans-serif;
    font-size:var(--fs-input);

    padding:10px 2px;
    outline:none;

    transition:border-color .3s ease;
}

.form-field input:focus,
.form-field textarea:focus{
    border-bottom-color:var(--border-focus, rgba(255,255,255,.85));
}

.form-field textarea{
    resize:vertical;
    min-height:130px;
    line-height:1.5;
}

.form-field input::placeholder,
.form-field textarea::placeholder{
    color:var(--text-placeholder, rgba(255,255,255,.46));
}

.contact-submit{
    align-self:flex-start;
    margin-top:8px;

    background:transparent;
    border:1px solid var(--cta-border, rgba(255,255,255,.4));
    color:var(--text, white);

    font-family:"Space Grotesk", sans-serif;
    font-weight:700;
    font-size:var(--fs-base);
    letter-spacing:.12em;
    text-transform:uppercase;

    padding:15px 36px;
    cursor:pointer;

    transition:background-color .3s ease, color .3s ease;
}

.contact-submit:hover{
    background-color:var(--cta-hover-bg, white);
    color:var(--cta-hover-color, black);
}

.form-status{
    font-size:var(--fs-base);
    line-height:1.6;
    margin-top:4px;
}

.form-status.is-success{
    color:var(--success, rgba(140,255,170,.85));
}

.form-status.is-error{
    color:var(--error, rgba(255,140,140,.85));
}

.contact-note{
    font-size:var(--fs-sm);
    color:var(--text-faint, rgba(255,255,255,.35));
    margin-bottom:48px;
    max-width:540px;
    line-height:1.6;
}

/* ===========================================================
   PLACEHOLDER BLOCK
   Marks where real content is not ready yet. There were three
   near-identical versions of this — in about.css, and twice in
   capabilities.css — which is how a system starts drifting.

   NEVER fill one of these with a stock photo or invented copy.
   An honest gap is better than a fake, and the whole copy voice
   depends on that being true.
=========================================================== */

.placeholder-box{
    display:flex;
    align-items:center;
    justify-content:center;
    text-align:center;
    padding:14px;

    background:linear-gradient(160deg, var(--bg-alt, rgba(255,255,255,.05)), transparent);
    /* Same anchoring line as a real picture. A placeholder occupies an
       image slot, so it should sit on the page the same way one does -
       this rule comes after the framed-media block and would otherwise
       put the old neutral hairline back on the team photo. */
    border:1px solid var(--media-border);
}

.placeholder-label{
    font-family:"Space Mono", monospace;
    font-size:var(--fs-2xs);
    letter-spacing:.1em;
    text-transform:uppercase;
    color:var(--text-muted, rgba(255,255,255,.6));
}

.hp-field{
    position:absolute;
    left:-9999px;
    width:1px;
    height:1px;
    opacity:0;
    pointer-events:none;
}
