/* Page rhythm: compact supporting tools, generous separation between tasks. */
html{scroll-behavior:auto;scroll-padding-top:0}
body[data-view] .service-choices{display:none}
body[data-view] .quote-section,body[data-view] .process-section{padding-top:32px}
body[data-view] .section-heading{align-items:flex-start}
body[data-view] main{min-height:calc(100vh - 208px)}
body[data-view] #quote,body[data-view] #process{scroll-margin-top:0}
.site-header{display:grid;grid-template-columns:1fr auto 1fr;gap:24px}
.site-header .brand{justify-self:start}
.site-header nav{display:flex;gap:8px}
.site-header nav a[aria-current]{background:var(--soft);color:var(--ink);box-shadow:inset 0 -2px var(--accent)}
.site-header nav a:focus-visible{outline:2px solid var(--accent);outline-offset:4px}
.site-header nav a{display:flex;align-items:center;justify-content:center;width:96px;min-height:48px;font-size:12px;line-height:16px;letter-spacing:-.02em}
.site-header .header-cta{justify-self:end}
#quote,#preview-workspace,#process{scroll-margin-top:24px}

#photo-status:empty{display:none}
.upload-zone:focus-visible{outline:2px solid var(--accent);outline-offset:4px}
.modeling-form [aria-invalid=true]{outline:2px solid var(--danger);outline-offset:4px}
/* A request error sits under the field it is about (app.js showRequestError), as wide as that field. */
.modeling-field>.form-error,.config-section>.form-error{max-width:none}
body input::placeholder,body textarea::placeholder,.modeling-form input::placeholder,.modeling-form textarea::placeholder{color:color-mix(in srgb,var(--muted) 65%,var(--surface,#fff));opacity:1;font-weight:400}
.contact-fields .modeling-field{gap:8px}
.contact-fields .modeling-field:nth-child(n+3){grid-column:1/-1}
body[data-theme=a] .hero{padding:48px 0;gap:48px}
body[data-theme=a] .hero-art{height:416px}
body[data-theme=a] .hero-copy{gap:24px}
body[data-theme=a] .hero h1{font-size:48px;line-height:56px;letter-spacing:-.02em}
.hero-copy>p{max-width:32em;line-height:28px;letter-spacing:-.02em}
.hero-actions{gap:24px}
.hero-actions .primary-button{min-width:192px}
.hero-actions .text-link{min-width:128px}
.quote-section{padding-top:0}
.section-heading{margin-bottom:24px}
.service-choices{gap:16px;margin-bottom:32px;grid-template-columns:repeat(2,minmax(0,1fr))}
.service-choice{padding:24px;min-height:96px}
.quote-layout,.modeling-layout{gap:32px}
.config-panel,.quote-summary,.modeling-guide{padding:24px}
.config-section{gap:16px}
.config-section+.config-section{margin-top:32px;padding-top:32px}
#materials{gap:24px}
body[data-theme=a] .preview-workspace{padding:24px 0 32px;gap:24px;box-shadow:0 -1px var(--line)}
.preview-heading{gap:16px}
.preview-grid{gap:32px}
.model-source-note{padding:16px;gap:32px;background:transparent;box-shadow:inset 0 0 0 1px var(--line)}
.model-source-copy>p.viewer-caption{max-width:36em}
.preview-workspace[data-loaded=false] .model-viewport{height:144px}
.preview-workspace[data-loaded=false] .viewer-empty{flex-direction:row;gap:16px;padding:24px}
.preview-workspace[data-loaded=false] .viewer-empty svg{width:32px;height:32px}
.preview-workspace[data-loaded=false] .viewer-empty>span{display:none}
/* 3D preview tools: one open at a time beside the view (details name=viewer-tools), each row showing its current
   value; the view's own buttons and the cut's legend sit on the picture. */
.viewer-tool{box-shadow:0 1px var(--line)}
/* A row is 56 tall; its pressable part is 48 of it, so two closed rows' targets stay 8 apart. */
.viewer-tool>summary{display:flex;align-items:center;gap:16px;min-height:48px;padding:12px 0;margin:4px 0;cursor:pointer;list-style:none;font-weight:750;letter-spacing:-.02em}
.viewer-tool>summary::-webkit-details-marker{display:none}
.viewer-tool>summary::after{content:'';flex:none;width:8px;height:8px;margin:0 4px 4px 0;border:solid var(--muted);border-width:0 2px 2px 0;transform:rotate(45deg)}
.viewer-tool[open]>summary::after{margin:4px 4px 0 0;transform:rotate(-135deg)}
.viewer-tool>summary:focus-visible{outline:2px solid var(--accent);outline-offset:4px}
.tool-value{margin-left:auto;font-size:12px;line-height:16px;font-weight:400;color:var(--muted);letter-spacing:-.02em;text-align:right}
.tool-value[data-fits=false]{color:#ab382e}
.viewer-tool>section{display:flex;flex-direction:column;gap:16px;padding-bottom:32px}
.layer-control,.bands-group{display:flex;flex-direction:column;gap:8px}
.bands-group{margin-top:16px}
.bands-group h3{font-weight:550}
.band-card>i{box-shadow:inset 0 0 0 1px #0002} /* a white filament's mark stays visible on the white card */
.size-group .printer-envelope{margin-top:8px;padding-top:0;box-shadow:none;gap:8px}
.preview-controls .viewer-stack{gap:8px}
.view-buttons{position:absolute;top:16px;right:16px;z-index:1;display:flex;gap:8px}
.model-viewport .view-buttons button{min-height:32px;min-width:32px;padding:8px 12px;font-size:12px;line-height:16px;font-weight:550;color:#343d37;background:rgb(255 255 255/.88);box-shadow:inset 0 0 0 1px rgb(0 0 0/.12)}
.model-viewport .view-buttons button:hover{background:#fff}
.slice-note{position:absolute;left:16px;bottom:16px;max-width:calc(100% - 32px);z-index:1;display:flex;flex-wrap:wrap;align-items:center;gap:8px 24px;padding:8px 12px;border-radius:4px;color:#343d37;background:rgb(255 255 255/.88);box-shadow:inset 0 0 0 1px rgb(0 0 0/.12);pointer-events:none}
.slice-note .slice-legend{gap:12px;line-height:16px}
.slice-note .slice-legend>span{gap:4px}
.slice-note p{margin:0;font-size:12px;line-height:20px;letter-spacing:-.02em}
.quote-summary{position:sticky;top:24px}
.quote-summary .price{font-size:48px;line-height:56px}
.modeling-input-grid{gap:24px 16px}
.modeling-form textarea{max-width:100%}
.modeling-guide{gap:32px}
.site-footer{margin-top:48px;padding:24px 0;flex-wrap:wrap}
/* Business details the first page must show (전자상거래법), on a row of their own under the brand and links; the
   markup breaks them into short lines, so the paragraph width cap is lifted to let them take the row. */
.footer-biz{flex-basis:100%;max-width:none;margin:0}
.small,.viewer-caption,.preview-controls label{letter-spacing:-.02em}
.small{line-height:20px}
.price-unit{letter-spacing:0}
@media(max-width:960px){
 .quote-summary{position:static}
 .model-source-note{gap:16px}
 .preview-controls{padding-top:0!important}
 .preview-workspace[data-loaded=false] .viewer-empty{flex-wrap:wrap}
}

/* Readable navigation and request-form supporting text. */
.site-header nav a,.hero-actions .text-link{font-size:16px;line-height:24px;letter-spacing:-.02em}
/* Notes, counts and sub-labels: 12, the small step of the scale (14 sat too close to 16 to read as a level). */
.modeling-form .small,.modeling-form .upload-help,.modeling-form .dimension-grid label,.modeling-guide .small,
.service-choice>span:nth-child(2)>span{font-size:12px;line-height:20px;letter-spacing:-.02em;font-weight:400;color:var(--muted)}
/* What to prepare, what it costs and what comes next is read before writing the request: body size. */
.modeling-guide-section ul,.modeling-costs,.modeling-steps,.sketch-guide p{font-size:16px;line-height:28px;letter-spacing:-.02em;font-weight:400;color:var(--muted)}
.modeling-form .upload-zone strong{font-size:16px;line-height:24px}
.modeling-form .step-heading h3,.modeling-guide-section h3{font-size:16px;line-height:24px;font-weight:750;color:var(--ink)}
.modeling-field>label,.modeling-field>span{font-weight:550}
.modeling-form input,.modeling-form textarea,.modeling-form select{font-weight:400}
.modeling-form input::placeholder,.modeling-form textarea::placeholder{font-size:16px}
.modeling-costs dd{font-weight:550;color:var(--ink)}
.modeling-guide .small{font-size:12px;line-height:20px!important}
@media(max-width:640px){
 body[data-theme=a] .site-header{height:80px}
 body[data-theme=a] .hero{padding:32px 0;gap:32px}
 body[data-theme=a] .hero-copy{gap:24px}
 body[data-theme=a] .hero h1{font-size:48px;line-height:56px}
 body[data-theme=a] .hero-art{height:320px}
 .hero-actions{align-items:stretch;flex-direction:column;gap:8px;width:100%}
 .hero-actions .text-link{justify-content:center}
 .service-choices{grid-template-columns:1fr}
 .service-choice{padding:16px;min-height:96px}
 .config-panel,.quote-summary,.modeling-guide{padding:16px}
 .model-source-note{padding:16px}
 .preview-workspace[data-loaded=false] .viewer-empty{padding:16px;gap:16px}
 .preview-workspace[data-loaded=false] .viewer-empty svg{display:none}
 .preview-workspace[data-loaded=false] .viewer-empty strong{font-size:16px;line-height:24px}
 .modeling-input-grid{grid-template-columns:1fr;gap:24px}
 .site-footer{gap:16px;flex-wrap:wrap}
}

@media(max-width:760px){
 body .site-header,body[data-theme=a] .site-header{height:auto;grid-template-columns:1fr auto;gap:16px;padding:16px 0}
 .site-header nav{grid-column:1/-1;grid-row:2;display:grid;grid-template-columns:repeat(3,round(down,calc((100% - 16px)/3),4px));gap:8px}
 .site-header nav a{width:100%;min-height:48px}
}

/* Order request inside the quote summary (shown after a model is loaded) */
.quote-summary:has(#order-form:not([hidden])){position:static}
.order-request{display:flex;flex-direction:column;gap:24px;margin-top:16px;padding-top:24px;box-shadow:0 -1px var(--line)}
.order-request-heading{display:flex;flex-direction:column;gap:8px;margin-bottom:-8px}
.order-request-heading h3{font-size:16px;line-height:24px;font-weight:750}
.order-request textarea{min-height:96px}
.order-request .primary-button{width:100%}
.consent-check{display:flex;flex-direction:row;align-items:flex-start;gap:8px;min-height:44px;font-size:16px;line-height:28px;color:var(--ink);cursor:pointer}
.consent-check input{flex:none;width:24px!important;height:24px!important;margin:4px 0 0;accent-color:var(--accent);box-shadow:none!important}
.consent-check a{text-decoration:underline;text-underline-offset:4px}
.footer-links{display:flex;flex-wrap:wrap;gap:8px 24px}.footer-links a{min-height:32px}
.order-request .small{font-size:12px;line-height:20px}.order-request .small:empty{display:none}
.order-request{word-break:keep-all}
.request-actions{display:flex;flex-wrap:wrap;align-items:center;gap:16px}
/* Floating shortcut to the quote request form while a model is loaded and the form is off screen. */
.quote-jump{position:fixed;right:24px;bottom:24px;z-index:20;min-height:48px;padding:12px 24px;gap:16px;box-shadow:0 8px 24px rgb(0 0 0/.16)}
@media(max-width:640px){.quote-jump{left:16px;right:16px;bottom:16px;justify-content:center}}
.request-review .small:empty{display:none}

/* Type and spacing (2026-10-22). One scale on every screen: 48 display, 32 page title (24 on phones), 16 for
   everything people read or press (titles 750, labels 550, option names 650, text 400), 12 for notes, units and
   counts; neighbouring sizes stay 1.25x apart. Gaps: 8 inside a group, 16 under a title, 24 between fields and groups,
   32 between steps, 48 between the big blocks of a page. */
.section-heading{align-items:center}
.section-heading h2{font-size:32px;line-height:40px;letter-spacing:-.03em}
#quote .step-heading :is(h2,h3){font-size:16px;line-height:24px;font-weight:750;letter-spacing:-.02em}
.quote-summary>h3,.process-grid h3,.model-source-copy h3{line-height:24px}
.config-section,.request-review{gap:24px}
.config-section>.step-heading,.request-review>.step-heading,.preview-heading{margin-bottom:-8px}
.photo-list{margin-top:8px}
.viewer-upload-group .upload-zone{margin-top:0}
body[data-theme=a] .preview-workspace{padding-bottom:16px}
/* Options: the name at body size, its note in small type right under it. */
.material-option,.segment-group button{gap:4px}
.material-option>span:first-child{font-family:inherit;font-size:16px;line-height:24px;font-weight:650;letter-spacing:-.02em}
.segment-group button{font-weight:650}
.material-grid{gap:8px}
.material-option .small,.segment-group .small{line-height:20px;font-weight:400}
.field-label{font-size:16px;line-height:24px;font-weight:550;color:var(--ink);letter-spacing:-.02em}
/* Summary: the title, the price and its basis read as one; the facts and the notes follow as their own groups. */
.quote-summary{gap:8px}
.quote-summary>h3,.quote-summary>p.small{margin-top:0}
.quote-summary .price-facts,.quote-summary #discount-note{margin-top:16px}
/* What the price includes, in the words of the order page's confirmed quote: label, the list, shipping as a note. */
.price-facts{display:flex;flex-direction:column;gap:4px;margin:0}
.price-facts dt,.price-facts-note{font-size:12px;line-height:20px;letter-spacing:-.02em;color:var(--muted)}
.price-facts dd{margin:0;font-size:16px;line-height:24px}
.price-facts dd.price-facts-note{font-size:12px;line-height:20px}
.discount-note{display:flex;flex-direction:column;gap:8px}
/* The note under the customer's own price: one line while calculating, two once priced; the room for two is kept, so
   nothing below moves when the price arrives. */
#estimate-note{min-height:40px}
/* 3D preview tools: labels, buttons and menus at the size of every other form; readouts and notes stay 12. */
.preview-workspace button,.preview-workspace summary,.makerworld-link{font-size:16px;line-height:24px}
.preview-workspace label:not(.upload-zone){font-size:16px;line-height:24px;font-weight:550}
.preview-workspace :is(select,input:not([type=range],[type=file])){font-size:16px;font-weight:400}
.band-card span span{font-size:16px;line-height:24px}
.band-card small{line-height:20px}
.printer-envelope .viewer-stack span{font-size:16px;line-height:24px;font-weight:650}
.paint-group>.filament-search-field{margin-top:16px}
.photo-card button{font-size:16px;line-height:24px}
.demo-pill,.live-indicator,.discount-note,.stock-quote-note,.request-review dt,.photo-card>span{letter-spacing:-.02em}
/* Home: on tall monitors the art grows into the empty lower half; the hero stays right under the header, where the logo
   and the menu always bring it (centred, it seemed to drop down the page). The drawing keeps its proportions in any box
   (it used to stretch to the box). */
#object-canvas{object-fit:cover}
@media(min-width:641px) and (max-width:960px){#object-canvas{object-fit:contain}} /* wide, low box: cover would crop the top */
/* The 3D view: a studio backdrop (light in the middle, darker to the edges) so a white print stands out from it. */
body[data-theme=a] .model-viewport{background:radial-gradient(120% 100% at 50% 32%,#fdfdfd 0%,#eff1f0 55%,#dfe3e1 100%)}
@media(min-width:961px){
 body[data-theme=a] .hero-art{height:clamp(416px,100vh - 448px,640px)}
 /* The 3D view takes the window's height less its toolbar, up to about a square, and stays in sight beside the tools
    while they scroll: what a tool does shows only in the view. Rounded to the 8 px grid. */
 .preview-workspace[data-loaded=true] .model-viewport{height:512px;height:clamp(448px,round(down,100dvh - 176px,8px),768px)}
 .preview-main{position:sticky;top:24px}
}
@media(max-width:640px){
 .section-heading{align-items:flex-start;gap:8px}
 .section-heading h2{font-size:24px;line-height:32px}
 .quantity-section{gap:16px}
 .segment-group button{font-size:16px}
 /* Materials list like the quality and strength options on a phone: one row each, name left and note right. */
 .material-grid{grid-template-columns:1fr}
 .material-option{flex-direction:row;justify-content:space-between;min-height:56px;padding:16px}
}
/* A setting's name with its 「?」 note (shown on hover or keyboard focus, or kept open by a tap: app.js). The note opens
   above the name, so the field it explains stays free to tap. The circle is 20 px; its press area, 32 × 32, reaches up
   from the name's line, not down, so it stays 8 px off the field below. */
.field{display:flex;flex-direction:column;gap:8px;min-width:0}
.field-head{position:relative;display:flex;align-items:center;gap:4px;min-width:0}
.help{display:flex}
.help>.help-button{position:relative;flex:none;width:20px;height:20px;min-width:0;min-height:0;padding:0;border-radius:50%;background:none;box-shadow:inset 0 0 0 1px var(--muted);color:var(--muted);font:700 12px/20px Arial,sans-serif;letter-spacing:0;cursor:help}
.help>.help-button::before{content:'';position:absolute;inset:-10px -6px -2px}
.help>.help-button:hover:not(:disabled){background:var(--soft);color:var(--ink)}
.help-tip{display:none;position:absolute;bottom:calc(100% + 8px);left:0;z-index:20;width:max-content;max-width:min(320px,calc(100vw - 32px));padding:8px 12px;border-radius:4px;background:var(--ink);color:var(--page);font-size:12px;line-height:20px;font-weight:400;letter-spacing:-.02em;white-space:normal;box-shadow:0 4px 16px rgb(0 0 0/.16)}
.help-tip::before{content:'';position:absolute;left:0;right:0;top:100%;height:8px} /* the pointer crosses the gap to the note */
.help.below .help-tip{bottom:auto;top:calc(100% + 8px)}
.help.below .help-tip::before{top:auto;bottom:100%}
.transform-fields>.field:nth-child(even) .help-tip{left:auto;right:0} /* the right column's notes open leftwards */
.help.open:not(.closed) .help-tip,.help:not(.closed) .help-button:focus-visible+.help-tip{display:block}
@media(hover:hover){.help:not(.closed):hover .help-tip{display:block}}
