Files
toolvana/public/assets/css/app.css
T
deepseek beaf0e1f37 Toolvana: production-ready media tools platform (CodeIgniter 4)
- 134-tool registry with programmatic SEO (unique titles/H1/descriptions,
  JSON-LD graphs, sitemap index, canonical 301 enforcement via required filter)
- DB-backed job queue (SKIP LOCKED) with drivers: Ffmpeg, Images (GD),
  Pdf (qpdf/gs/poppler), Youtube (thumbnails), Qr (server-side PNG)
- Security: SSRF guard, MIME validation, rate limits, API-key auth,
  bcrypt admin login, security headers
- Admin panel: dashboard, tools/categories/guides CRUD, SEO audit,
  analytics, job inspector with retry, system health, feature flags
- Docker deployment (nginx + web/api FPM pools + scalable workers),
  PHPUnit suite (19 tests / 1139 assertions), PWA manifest + service worker
2026-08-23 07:10:30 +00:00

197 lines
13 KiB
CSS
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/* ==========================================================================
Toolvana design system — single stylesheet, no framework, no webfonts.
System font stack keeps LCP fast and CLS at zero.
========================================================================== */
:root {
--brand-50:#f5f3ff; --brand-100:#ede9fe; --brand-500:#7c3aed; --brand-600:#6d28d9;
--brand-700:#5b21b6; --brand-900:#2e1065;
--ink-900:#111827; --ink-700:#374151; --ink-500:#6b7280; --ink-300:#d1d5db;
--paper:#ffffff; --bg:#fafafa; --ok:#059669; --err:#dc2626; --warn:#d97706;
--radius:14px; --radius-sm:9px;
--shadow-sm:0 1px 2px rgb(17 24 39 / .06),0 1px 3px rgb(17 24 39 / .08);
--shadow-md:0 4px 12px rgb(17 24 39 / .10);
--maxw:1080px;
font-size:16px;
}
* { box-sizing:border-box; }
html { -webkit-text-size-adjust:100%; scroll-behavior:smooth; }
body {
margin:0; background:var(--bg); color:var(--ink-900);
font-family:system-ui,-apple-system,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif;
line-height:1.6; text-rendering:optimizeLegibility;
}
img,svg,video { max-width:100%; height:auto; }
.icon { width:1.25em; height:1.25em; vertical-align:-.22em; flex:none; }
a { color:var(--brand-600); text-decoration:none; }
a:hover { text-decoration:underline; }
:focus-visible { outline:3px solid var(--brand-500); outline-offset:2px; border-radius:4px; }
.skip-link{position:absolute;left:-9999px;top:0;background:#fff;padding:.6rem 1rem;z-index:99;border-radius:0 0 var(--radius-sm) 0}
.skip-link:focus{left:0}
/* ---------- header ---------- */
.site-header{background:var(--paper);border-bottom:1px solid #eee;position:sticky;top:0;z-index:40}
.site-header .inner{max-width:var(--maxw);margin:0 auto;display:flex;align-items:center;gap:1.2rem;padding:.65rem 1.25rem}
.logo{display:flex;align-items:center;gap:.55rem;font-weight:800;font-size:1.18rem;color:var(--ink-900);letter-spacing:-.02em}
.logo:hover{text-decoration:none}
.logo-mark{width:34px;height:34px;border-radius:10px;background:linear-gradient(135deg,var(--brand-600),#a855f7);display:inline-flex;align-items:center;justify-content:center;color:#fff}
.main-nav{margin-left:auto;display:flex;align-items:center;gap:1rem}
.main-nav a{color:var(--ink-700);font-weight:550;font-size:.95rem;padding:.35rem .15rem}
.nav-toggle{display:none;margin-left:auto;background:none;border:0;color:var(--ink-700);padding:.4rem;cursor:pointer}
/* ---------- hero ---------- */
.hero{background:linear-gradient(160deg,var(--brand-700) 0%,#7c3aed 60%,#9333ea 100%);color:#fff;padding:3.4rem 1.25rem 4.2rem;text-align:center}
.hero h1{font-size:clamp(1.8rem,4.5vw,2.9rem);line-height:1.15;margin:.4rem auto 0;font-weight:850;letter-spacing:-.03em;max-width:820px}
.hero .tagline{font-size:clamp(1rem,2vw,1.2rem);opacity:.93;max-width:600px;margin:1rem auto 1.8rem}
.hero-search{display:flex;max-width:560px;margin:0 auto;background:#fff;border-radius:999px;padding:.3rem;box-shadow:var(--shadow-md)}
.hero-search input[type=search]{flex:1;border:0;font-size:1.02rem;padding:.72rem .5rem .72rem 1.15rem;min-width:0;background:none;color:var(--ink-900)}
.hero-search input:focus{outline:none}
.hero-search button{border:0;background:var(--ink-900);color:#fff;border-radius:999px;padding:.68rem 1.5rem;font-weight:650;cursor:pointer;font-size:.97rem}
.hero-stats{margin-top:1.6rem;font-size:.92rem;opacity:.85}
/* ---------- layout blocks ---------- */
.wrap{max-width:var(--maxw);margin:0 auto;padding:0 1.25rem}
section.block{padding:2.6rem 0}
section.block.tight{padding:1.6rem 0}
h2.section-title{font-size:1.45rem;font-weight:800;letter-spacing:-.02em;margin:0 0 1.2rem;display:flex;align-items:center;gap:.6rem}
h2.section-title .see-all{margin-left:auto;font-size:.9rem;font-weight:600}
/* ---------- cards ---------- */
.grid{display:grid;gap:1rem}
.grid.cols-4{grid-template-columns:repeat(4,1fr)}
.grid.cols-3{grid-template-columns:repeat(3,1fr)}
.grid.cols-2{grid-template-columns:repeat(2,1fr)}
.card{background:var(--paper);border-radius:var(--radius);padding:1.15rem 1.2rem;box-shadow:var(--shadow-sm);transition:transform .12s ease,box-shadow .12s ease;display:block;color:inherit}
a.card:hover{transform:translateY(-2px);box-shadow:var(--shadow-md);text-decoration:none}
.card h3,.card h2{margin:0 0 .3rem;font-size:1.02rem;font-weight:700;letter-spacing:-.01em}
.card p{margin:0;color:var(--ink-500);font-size:.88rem;line-height:1.5}
.card .icon-wrap{width:42px;height:42px;border-radius:11px;background:var(--brand-50);color:var(--brand-600);display:flex;align-items:center;justify-content:center;margin-bottom:.75rem}
.card .icon-wrap .icon{width:22px;height:22px}
.badge{display:inline-block;font-size:.68rem;font-weight:750;letter-spacing:.06em;text-transform:uppercase;background:var(--brand-50);color:var(--brand-700);padding:.18rem .55rem;border-radius:999px}
.meta-line{font-size:.78rem;color:var(--ink-500);margin-top:.55rem}
.cat-card{display:flex;flex-direction:column;align-items:flex-start;gap:.4rem}
.cat-card .count{font-size:.8rem;color:var(--ink-500)}
/* ---------- tool page ---------- */
.tool-head{margin:2.2rem 0 1rem}
.tool-head h1{font-size:clamp(1.6rem,4vw,2.3rem);font-weight:830;letter-spacing:-.03em;margin:.35rem 0 .4rem;line-height:1.18}
.breadcrumbs ol{list-style:none;display:flex;flex-wrap:wrap;gap:.45rem;margin:1.4rem 0 0;padding:0;font-size:.85rem;color:var(--ink-500)}
.breadcrumbs li+li::before{content:"→";margin-right:.45rem;color:var(--ink-300)}
.breadcrumbs a{color:var(--ink-500)}
.breadcrumbs [aria-current]{color:var(--ink-900);font-weight:600}
.tool-panel{background:var(--paper);border-radius:18px;box-shadow:var(--shadow-sm);padding:1.8rem;margin-top:1.2rem}
.url-form{display:flex;flex-direction:column;gap:.85rem}
.url-row{display:flex;gap:.7rem}
.input-lg{flex:1;border:2px solid var(--ink-300);border-radius:12px;padding:.95rem 1.05rem;font-size:1.04rem;min-width:0;transition:border-color .15s}
.input-lg:focus{outline:none;border-color:var(--brand-500)}
.btn-primary{border:0;background:linear-gradient(135deg,var(--brand-600),#9333ea);color:#fff;font-size:1.05rem;font-weight:700;padding:.95rem 2rem;border-radius:12px;cursor:pointer;min-height:54px;white-space:nowrap}
.btn-primary:hover{filter:brightness(1.06)}
.btn-primary[disabled]{opacity:.6;cursor:not-allowed}
.hint{font-size:.83rem;color:var(--ink-500)}
.dropzone{border:2.5px dashed var(--ink-300);border-radius:16px;padding:2.6rem 1.4rem;text-align:center;cursor:pointer;transition:border-color .15s,background .15s;background:#fcfcff}
.dropzone:hover,.dropzone.dragover{border-color:var(--brand-500);background:var(--brand-50)}
.dropzone .icon{width:38px;height:38px;color:var(--brand-600)}
.dropzone strong{display:block;font-size:1.05rem;margin:.6rem 0 .2rem}
.dropzone span{font-size:.86rem;color:var(--ink-500)}
.file-chip{display:flex;align-items:center;gap:.75rem;background:var(--brand-50);border-radius:11px;padding:.7rem .9rem;font-size:.9rem}
.file-chip .name{font-weight:650;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.file-chip button{margin-left:auto;border:0;background:none;color:var(--err);cursor:pointer;font-size:.82rem;font-weight:650}
.status-flow{margin-top:1rem}
.progress-track{height:9px;border-radius:999px;background:#eceefc;overflow:hidden}
.progress-fill{height:100%;width:0;background:linear-gradient(90deg,var(--brand-500),#a855f7);border-radius:999px;transition:width .35s ease}
.stages{list-style:none;display:flex;justify-content:space-between;padding:0;margin:.7rem 0 0;font-size:.76rem;color:var(--ink-500)}
.stages li.done{color:var(--ok);font-weight:650}
.stages li.active{color:var(--brand-700);font-weight:700}
.result-panel{margin-top:1.1rem;border:1px solid #e5e7eb;border-radius:14px;padding:1.1rem;display:none}
.result-panel.show{display:block}
.result-meta{display:grid;grid-template-columns:auto 1fr auto auto;gap:.4rem 1.1rem;font-size:.92rem;align-items:center}
.result-actions{margin-top:.9rem;display:flex;gap:.7rem;flex-wrap:wrap}
.notice{border-left:4px solid var(--warn);background:#fffbeb;padding:.8rem 1rem;border-radius:0 10px 10px 0;font-size:.92rem;margin-top:1rem}
.notice.error{border-color:var(--err);background:#fef2f2}
details.advanced{margin-top:1rem;border:1px solid #e8e8f0;border-radius:11px;padding:.75rem 1rem}
details.advanced summary{cursor:pointer;font-weight:650;font-size:.92rem;color:var(--ink-700)}
.opt-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));gap:.9rem;padding-top:.9rem}
.opt-grid label{display:block;font-size:.8rem;font-weight:650;color:var(--ink-700);margin-bottom:.25rem}
.opt-grid select,.opt-grid input[type=number],.opt-grid input[type=text]{width:100%;border:1.5px solid var(--ink-300);border-radius:9px;padding:.5rem .6rem;font-size:.92rem}
.faq details{background:var(--paper);border-radius:var(--radius-sm);box-shadow:var(--shadow-sm);margin-bottom:.65rem}
.faq summary{cursor:pointer;font-weight:650;padding:.9rem 1.1rem;list-style:none;display:flex;justify-content:space-between;align-items:center;gap:1rem}
.faq summary::-webkit-details-marker{display:none}
.faq summary::after{content:"+";font-size:1.3rem;color:var(--brand-600);line-height:1}
.faq details[open] summary::after{content:""}
.faq .answer{padding:0 1.1rem .95rem;color:var(--ink-700);font-size:.94rem}
.steps{counter-reset:step;list-style:none;padding:0;margin:0;display:grid;gap:.8rem}
.steps li{counter-increment:step;background:var(--paper);border-radius:var(--radius-sm);box-shadow:var(--shadow-sm);padding:1rem 1.1rem 1rem 3.4rem;position:relative;font-size:.94rem}
.steps li strong{display:block}
.steps li::before{content:counter(step);position:absolute;left:.95rem;top:1rem;width:26px;height:26px;border-radius:50%;background:var(--brand-600);color:#fff;font-weight:750;display:flex;align-items:center;justify-content:center;font-size:.85rem}
.chips{display:flex;flex-wrap:wrap;gap:.45rem;margin:.4rem 0}
.chip{background:var(--paper);border:1px solid #e5e7eb;border-radius:999px;padding:.28rem .8rem;font-size:.84rem;font-weight:600;color:var(--ink-700)}
.chip:hover{border-color:var(--brand-500);color:var(--brand-600);text-decoration:none}
.prose{max-width:74ch}
.prose h2{font-size:1.3rem;margin:2rem 0 .7rem;letter-spacing:-.02em}
.prose p,.prose ul,.prose ol{color:var(--ink-700);font-size:.98rem}
.prose table{border-collapse:collapse;width:100%;font-size:.9rem;margin:1rem 0}
.prose th,.prose td{border:1px solid #e5e7eb;padding:.5rem .7rem;text-align:left}
.prose th{background:var(--brand-50)}
.prose code{background:#f3f0ff;padding:.1rem .35rem;border-radius:5px;font-size:.88em}
/* ---------- utility/text tools ---------- */
.io-grid{display:grid;grid-template-columns:1fr 1fr;gap:1rem}
textarea.tool-area{width:100%;min-height:190px;border:2px solid var(--ink-300);border-radius:12px;padding:.9rem;font:inherit;font-size:.95rem;resize:vertical}
textarea.tool-area:focus{outline:none;border-color:var(--brand-500)}
/* ---------- footer ---------- */
.site-footer{background:var(--paper);border-top:1px solid #eee;margin-top:3rem;padding:2.4rem 0 2rem;font-size:.9rem}
.footer-cols{display:grid;grid-template-columns:2fr 1fr 1fr 1fr;gap:2rem}
.footer-cols h4{margin:.2rem 0 .7rem;font-size:.82rem;text-transform:uppercase;letter-spacing:.08em;color:var(--ink-500)}
.footer-cols ul{list-style:none;padding:0;margin:0;display:grid;gap:.4rem}
.footer-bottom{display:flex;justify-content:space-between;gap:1rem;flex-wrap:wrap;color:var(--ink-500);font-size:.82rem;margin-top:2rem;padding-top:1.2rem;border-top:1px solid #f0f0f0}
/* ---------- errors / misc ---------- */
.center-page{max-width:640px;margin:4rem auto;padding:0 1.25rem;text-align:left}
.error-hero{text-align:center;padding:3.5rem 0 1rem}
.error-hero code.big{font-size:3.4rem;font-weight:850;color:var(--brand-200,#ddd6fe);letter-spacing:-.05em}
@media (max-width:900px){
.grid.cols-4{grid-template-columns:repeat(2,1fr)}
.grid.cols-3{grid-template-columns:repeat(2,1fr)}
.footer-cols{grid-template-columns:1fr 1fr}
.io-grid{grid-template-columns:1fr}
}
@media (max-width:620px){
.main-nav{
display:none;position:absolute;top:100%;left:0;right:0;background:var(--paper);
flex-direction:column;align-items:flex-start;padding:1rem 1.4rem;border-bottom:1px solid #eee;gap:.8rem;
box-shadow:var(--shadow-md)
}
.main-nav.open{display:flex}
.nav-toggle{display:inline-flex}
.url-row{flex-direction:column}
.btn-primary{width:100%}
.grid.cols-2,.grid.cols-3,.grid.cols-4{grid-template-columns:1fr}
.hero-search{flex-direction:row}
.result-meta{grid-template-columns:1fr auto}
.stages{flex-wrap:wrap;gap:.3rem;justify-content:flex-start}
.tool-panel{padding:1.2rem}
}
@media (prefers-reduced-motion:no-preference){
.progress-fill{animation:pulse 1.4s ease-in-out infinite alternate}
@keyframes pulse{from{opacity:1}to{opacity:.75}}
}